Python中如何实现Django models数据在30天后自动删除?

<br>class Post(models.Model):
<br>    body = TextField()
<br>    POST_STATUS = ((0,'草稿'), (1,'发表'), (2,'回收站'))
<br>    status = CharField(choice=POST_STATUS)
<br>    delete_date = DateField()
<br>```
<br>有一个 Post 的 Model 子类,想要把标记为回收站的文章,删除时间满 30 天后删除。
<br>
<br>我可以想到的实现方式是添加计划任务,每天扫一遍找出删除时间满 30 天的进行删除,但是有哪些更好的的实现方式呢?<br>Python中如何实现Django models数据在30天后自动删除?

10 回复

直接 SQL 命令操作 database,可以不?


用Django Celery Beat配合定时任务最靠谱。给你个完整方案:

# models.py
from django.db import models
from django.utils import timezone

class TemporaryData(models.Model):
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    expires_at = models.DateTimeField()
    
    @classmethod
    def create_with_expiry(cls, content, days=30):
        return cls.objects.create(
            content=content,
            expires_at=timezone.now() + timezone.timedelta(days=days)
        )
    
    def is_expired(self):
        return timezone.now() > self.expires_at
# tasks.py (Celery任务)
from celery import shared_task
from django.utils import timezone
from .models import TemporaryData

@shared_task
def cleanup_expired_data():
    """删除过期数据"""
    expired_count = TemporaryData.objects.filter(
        expires_at__lte=timezone.now()
    ).delete()[0]
    return f"删除了 {expired_count} 条过期数据"
# celery.py (Celery配置)
from celery import Celery
from celery.schedules import crontab

app = Celery('your_project')
app.config_from_object('django.conf:settings', namespace='CELERY')

app.conf.beat_schedule = {
    'cleanup-daily': {
        'task': 'your_app.tasks.cleanup_expired_data',
        'schedule': crontab(hour=0, minute=0),  # 每天凌晨执行
    },
}
# settings.py 配置
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_TIMEZONE = 'Asia/Shanghai'

部署后启动:

# 启动Celery worker
celery -A your_project worker --loglevel=info

# 启动Celery beat调度器
celery -A your_project beat --loglevel=info

这个方案的好处是:1)数据模型自带过期时间字段,查询高效;2)Celery Beat每天自动清理;3)可以随时手动执行清理任务。

用Celery搞定时任务最稳当。

crontab、celery 或者自己写个守护进程每天轮询

软删除比较简单, 插入时设定过期时间, 查询时过滤过期时间.

楼上根据时间软删除是正解。

class Post(models.Model):
expires_at = DateField()


def delete_post(post):
post.update(expires_at=now() + timedelta(days=30))

def list_posts():
Post.query.filter(expires_at < now() + timedelta(days=30)).all()

你的通过计划任务定时删除的实现方式就是最好的方式。

楼上们说的通过时间过滤的方式可行,但是不是最好的方式,在性能敏感的情况下甚至可以说是个很烂的方式。
明明是一个可以在业务低谷期离线运行的任务,却要加在每一个在线查询里面凭白消耗计算资源。

1.mysql 有基于时间的 trigger 可以实现这个功能( model.raw(“xxxx”))
2.后台起一个 demon 每天轮询 清除
3.在 model/middleware/view 中 调用一个检查过期的函数(如果对性能有要求 可以基于概率来做)

查询的时候,delete_time__lte=timezone.now - 30days

基于时间做软删除,真要在库里删掉的话在写个脚本轮询被

回到顶部