如何在Django模型中创建触发器删除1天未激活的用户?
在Django中自动删除1天未激活的用户记录
首先,你的User模型缺少创建时间字段,无法判断账号创建时长,所以第一步需要给模型添加created_at字段:
class User(AbstractBaseUser, PermissionsMixin): # ... 原有字段 ... first_name = models.CharField(max_length=150, blank=True) last_name = models.CharField(max_length=150, blank=True) is_active = models.BooleanField(default=False) # 添加创建时间字段,自动记录用户创建时间 created_at = models.DateTimeField(auto_now_add=True) # ... 原有方法 ... def __str__(self): return self.email def __getitem__(self,key): return self.__dict__[key]
添加后执行迁移命令:python manage.py makemigrations && python manage.py migrate
下面提供几种可行的实现方案,按推荐程度排序:
方案一:使用django-crontab(轻量定时任务,适合小型项目)
这是最简便的方案,利用系统crontab定时执行Django自定义命令。
步骤1:安装依赖
pip install django-crontab
步骤2:配置应用
在项目settings.py的INSTALLED_APPS中添加:
INSTALLED_APPS = [ # ... 其他应用 ... 'django_crontab', ]
步骤3:编写清理命令
在你的应用目录下创建management/commands/clean_inactive_users.py(需先创建management和commands文件夹,每个文件夹都要有__init__.py):
from django.core.management.base import BaseCommand from django.utils import timezone from datetime import timedelta from your_app_name.models import User # 替换为你的应用名 class Command(BaseCommand): help = '自动删除超过1天未激活的用户' def handle(self, *args, **options): # 计算1天前的时间点 cutoff_time = timezone.now() - timedelta(days=1) # 删除符合条件的用户,返回删除数量 deleted_count, _ = User.objects.filter( is_active=False, created_at__lt=cutoff_time ).delete() self.stdout.write(self.style.SUCCESS(f'已成功删除 {deleted_count} 个未激活用户'))
步骤4:配置定时任务
在settings.py末尾添加:
CRONJOBS = [ # 每天凌晨1点执行一次清理任务(crontab格式:分 时 日 月 周) ('0 1 * * *', 'django.core.management.call_command', ['clean_inactive_users']), ]
步骤5:启动定时任务
执行命令添加定时任务到系统crontab:
python manage.py crontab add
可通过以下命令查看/删除定时任务:
python manage.py crontab show python manage.py crontab remove
方案二:使用Celery + Celery Beat(适合中大型分布式项目)
如果你的项目已在用Celery处理异步任务,推荐此方案,支持分布式部署和灵活的任务调度。
步骤1:编写Celery任务
在应用目录下创建tasks.py:
from celery import shared_task from django.utils import timezone from datetime import timedelta from your_app_name.models import User # 替换为你的应用名 @shared_task def clean_inactive_users(): cutoff_time = timezone.now() - timedelta(days=1) deleted_count, _ = User.objects.filter( is_active=False, created_at__lt=cutoff_time ).delete() return f'已删除 {deleted_count} 个未激活用户'
步骤2:配置Celery Beat定时任务
在项目settings.py中添加Celery Beat调度配置:
from celery.schedules import crontab CELERY_BEAT_SCHEDULE = { # 每天凌晨1点执行清理任务 'daily-clean-inactive-users': { 'task': 'your_app_name.tasks.clean_inactive_users', # 任务路径 'schedule': crontab(hour=1, minute=0), # 也可按间隔执行:'schedule': timedelta(days=1), }, }
步骤3:启动Celery服务
分别启动Celery Worker和Beat调度器:
# 启动Worker处理任务 celery -A your_project_name worker -l info # 启动Beat调度定时任务 celery -A your_project_name beat -l info
方案三:数据库触发器(不推荐,维护成本高)
直接在数据库层面创建定时触发器,缺点是逻辑脱离Django代码,迁移时易遗漏,且不同数据库语法不兼容。以PostgreSQL为例:
步骤1:安装pg_cron扩展(PostgreSQL定时任务依赖)
CREATE EXTENSION IF NOT EXISTS pg_cron;
步骤2:创建清理函数和定时任务
-- 创建清理未激活用户的函数 CREATE OR REPLACE FUNCTION delete_inactive_users() RETURNS void AS $$ BEGIN DELETE FROM your_app_name_user -- 替换为你的用户表名(通常是应用名_user) WHERE is_active = FALSE AND created_at < NOW() - INTERVAL '1 day'; END; $$ LANGUAGE plpgsql; -- 设置每天凌晨1点执行清理 SELECT cron.schedule('daily-clean-inactive-users', '0 1 * * *', 'SELECT delete_inactive_users();');
注意事项
- 关联数据处理:如果有其他模型通过外键关联User,需确保外键字段设置了合理的
on_delete属性(如models.CASCADE自动删除关联数据,models.SET_NULL需字段允许为空),避免数据库外键约束错误。 - 执行频率:可根据业务需求调整定时任务执行频率,比如每6小时执行一次,减少数据库压力。
- 时区问题:确保Django的
TIME_ZONE设置正确,避免时间计算错误。
内容的提问来源于stack exchange,提问作者some nooby questions
相关产品推荐
相关产品推荐

