如何用Celery实现定时删除过期对象?当前24小时清理任务未执行
问题解决与实现方案
先搞定你的定时删除24小时文件无效问题
你的代码里有几个明显错误,还有些配置得确认:
1. 过滤条件完全写错了
你现在的delete_file任务里,过滤的是所有上传时间早于现在的文件,这肯定不是你要的24小时前的效果。改一下tasks.py里的逻辑:
from datetime import timedelta from django.utils import timezone from celery import shared_task from .models import Archivo @shared_task def delete_file(): # 算出24小时前的时间点 cutoff_time = timezone.now() - timedelta(hours=24) # 只删上传时间早于这个点的文件 files = Archivo.objects.filter(fecha_subida__lte=cutoff_time) if files.exists(): deleted_count, _ = files.delete() return f"已删 {deleted_count} 个文件" return "没找到符合条件的文件"
2. 一定要启动Celery Beat进程
定时任务是靠Celery Beat调度的,光启动worker没用,得同时开beat:
# 先启动worker celery -A arhi worker -l info # 新开个终端启动beat celery -A arhi beat -l info
生产环境里建议用supervisor或者systemd管理这俩进程,别关了终端就停了。
3. 确认任务路径和APP配置
检查beat_schedule里的任务路径tarea.tasks.delete_file:
- 确保你的Django app名字真的是
tarea,而且settings.py的INSTALLED_APPS里加了tarea - 要么确认
autodiscover_tasks()能找到这个任务,要么手动指定:app.autodiscover_tasks(['tarea'])
4. 时区得一致
Django的settings.py里的TIME_ZONE必须和Celery的timezone一样:
# settings.py TIME_ZONE = 'America/Bogota'
时区不一样的话,时间计算会出错,明明到24小时了也删不了。
5. 看日志找问题
启动worker和beat的时候加-l info日志级别,看看有没有任务执行的记录,有没有报错。比如worker日志里要是出现任务找不到、数据库连不上,就能立刻定位问题。
实现对象5分钟后自动删的两种办法
要是想实现单个文件上传后5分钟就删,不用每分钟轮询数据库,有俩更高效的方式:
方案1:用countdown延迟执行任务
创建Archivo对象的时候,直接调用删除任务并设5分钟延迟:
# 在创建文件的视图或者信号里写 from tarea.tasks import delete_single_file # 创建完对象后 archivo = Archivo.objects.create(file="你的文件名") # 300秒=5分钟后执行删除 delete_single_file.apply_async(args=[archivo.id], countdown=300)
对应的tasks.py要加单个删除的任务:
@shared_task def delete_single_file(archivo_id): try: archivo = Archivo.objects.get(id=archivo_id) archivo.delete() return f"已删文件 {archivo_id}" except Archivo.DoesNotExist: return f"文件 {archivo_id} 不存在"
方案2:用ETA指定执行时间
和countdown类似,不过是直接指定具体执行时间:
from datetime import timedelta eta_time = timezone.now() + timedelta(minutes=5) delete_single_file.apply_async(args=[archivo.id], eta=eta_time)
这种方式比定时轮询省资源,不用每次查一堆数据,精准触发单个文件的删除。
内容的提问来源于stack exchange,提问作者Json
相关产品推荐
相关产品推荐

