如何自动将Django模型的verify_code字段值在1分钟后置空?
Django模型字段1分钟后自动清除的实现方案
方案1:使用Celery异步延迟任务
这是精准定时处理的常用方案,适合需要严格按时清理的场景:
- 确保项目已配置好Celery(搭配Redis/RabbitMQ等消息队列)
- 定义清除验证码的异步任务:
# tasks.py from celery import shared_task from django.utils import timezone from .models import YourModel # 替换为你的实际模型类名 @shared_task def clear_verify_code(instance_id): try: instance = YourModel.objects.get(id=instance_id) # 二次校验时间,避免中途被手动修改 if instance.verification_timestamp and timezone.now() - instance.verification_timestamp >= timezone.timedelta(minutes=1): instance.verify_code = None instance.save(update_fields=['verify_code']) except YourModel.DoesNotExist: pass
- 修改模型的
save方法,触发延迟任务:
from django.utils import timezone from .tasks import clear_verify_code class YourModel(models.Model): verify_code = models.IntegerField(blank=True, null=True) verification_timestamp = models.DateTimeField(blank=True, null=True) def save(self, *args, **kwargs): # 判断是否为新设置的验证码 is_new_code = self.verify_code is not None if not self._state.adding: original_instance = YourModel.objects.get(id=self.id) is_new_code = is_new_code and original_instance.verify_code is None if self.verify_code is not None: self.verification_timestamp = timezone.now() super().save(*args, **kwargs) # 新设置验证码时,触发1分钟后的清理任务 if is_new_code: # 用实例ID作为任务ID,避免重复任务 clear_verify_code.apply_async( args=[self.id], countdown=60, task_id=f"clear_verify_code_{self.id}" )
方案2:数据库层面定时清理
不想引入异步服务的话,直接用数据库的定时任务功能处理:
PostgreSQL(依赖pg_cron扩展)
- 安装pg_cron扩展:
CREATE EXTENSION pg_cron;
- 创建每分钟执行的清理任务:
SELECT cron.schedule('clear_verify_code', '* * * * *', $$ UPDATE your_app_yourmodel SET verify_code = NULL WHERE verification_timestamp <= NOW() - INTERVAL '1 minute' AND verify_code IS NOT NULL; $$);
(替换your_app_yourmodel为模型对应的数据库表名)
MySQL(使用事件调度器)
- 开启事件调度器:
SET GLOBAL event_scheduler = ON;
- 创建定时清理任务:
CREATE EVENT clear_verify_code ON SCHEDULE EVERY 1 MINUTE DO UPDATE your_app_yourmodel SET verify_code = NULL WHERE verification_timestamp <= NOW() - INTERVAL 1 MINUTE AND verify_code IS NOT NULL;
方案3:请求时惰性清理
小流量项目可以采用这种无依赖方案,仅在实例被访问时检查并清理:
from django.utils import timezone class YourModel(models.Model): verify_code = models.IntegerField(blank=True, null=True) verification_timestamp = models.DateTimeField(blank=True, null=True) def save(self, *args, **kwargs): # 保存前先检查是否需要清理过期验证码 if self.verify_code is not None and self.verification_timestamp: if timezone.now() - self.verification_timestamp >= timezone.timedelta(minutes=1): self.verify_code = None if self.verify_code is not None: self.verification_timestamp = timezone.now() super().save(*args, **kwargs) # 或者在获取实例时触发清理 @classmethod def get(cls, *args, **kwargs): instance = super().get(*args, **kwargs) if instance.verify_code is not None and instance.verification_timestamp: if timezone.now() - instance.verification_timestamp >= timezone.timedelta(minutes=1): instance.verify_code = None instance.save(update_fields=['verify_code']) return instance
内容的提问来源于stack exchange,提问作者nima_ shadloo
相关产品推荐
相关产品推荐

