You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中使用SQLite创建触发器实现30天无评论问题自动删除

实现方案

前置准备

首先确认你的模型满足以下基础条件,没有的话需要先补全字段并执行迁移:

  • Question模型存在DateTimeField类型的created_at字段,用于记录问题发布时间,建议设置auto_now_add=True自动填充创建时间
  • Comment模型存在指向Question的外键字段,用于关联对应问题

示例模型参考:

from django.db import models

class Question(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

class Comment(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='comments')
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

注意:SQLite 作为嵌入式数据库没有内置的定时调度能力,无法实现到点自动执行的逻辑,以下触发器会在每次对question或comments表执行写入操作时,自动清理所有满足「发布满30天且无评论」的问题数据,如果你需要严格的到点自动清理,可以搭配系统级定时任务辅助。


步骤1:创建空迁移文件

Django的自定义SQL逻辑需要通过迁移文件同步到数据库,执行以下命令生成空迁移,将your_app_name替换为你的应用名:

python manage.py makemigrations your_app_name --empty

步骤2:在迁移文件中添加触发器逻辑

打开生成的迁移文件,替换内容如下,注意替换所有your_app_name为你的实际应用名,dependencies中的上一个迁移文件名也需要和你的项目匹配:

from django.db import migrations

class Migration(migrations.Migration):
    dependencies = [
        ('your_app_name', '0001_initial'),
    ]

    operations = [
        # 新增问题后触发清理
        migrations.RunSQL(
            """
            CREATE TRIGGER IF NOT EXISTS clean_old_question_after_insert
            AFTER INSERT ON your_app_name_question
            BEGIN
                DELETE FROM your_app_name_question
                WHERE created_at <= DATETIME('now', '-30 days')
                AND id NOT IN (SELECT DISTINCT question_id FROM your_app_name_comment);
            END;
            """,
            reverse_sql="DROP TRIGGER IF EXISTS clean_old_question_after_insert;"
        ),
        # 新增评论后触发清理
        migrations.RunSQL(
            """
            CREATE TRIGGER IF NOT EXISTS clean_old_question_after_comment_insert
            AFTER INSERT ON your_app_name_comment
            BEGIN
                DELETE FROM your_app_name_question
                WHERE created_at <= DATETIME('now', '-30 days')
                AND id NOT IN (SELECT DISTINCT question_id FROM your_app_name_comment);
            END;
            """,
            reverse_sql="DROP TRIGGER IF EXISTS clean_old_question_after_comment_insert;"
        )
    ]

步骤3:执行迁移生效

运行以下命令将触发器写入SQLite数据库:

python manage.py migrate

可选补充:定时全量清理

如果需要确保即使没有写入操作也能定期清理过期数据,可以自定义Django命令配合系统定时任务实现:

  1. 在应用目录下创建management/commands/clean_old_questions.py文件,内容如下:
from django.core.management.base import BaseCommand
from django.db import connection

class Command(BaseCommand):
    help = "清理发布满30天无评论的问题"

    def handle(self, *args, **options):
        with connection.cursor() as cursor:
            cursor.execute("""
                DELETE FROM your_app_name_question
                WHERE created_at <= DATETIME('now', '-30 days')
                AND id NOT IN (SELECT DISTINCT question_id FROM your_app_name_comment);
            """)
        self.stdout.write(self.style.SUCCESS(f"成功清理{cursor.rowcount}条过期无评论问题"))
  1. 在系统crontab中添加定时任务,示例为每天凌晨2点执行一次:
0 2 * * * /path/to/your/python/env/bin/python /path/to/your/project/manage.py clean_old_questions

内容的提问来源于stack exchange,提问作者Joeduciel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 21:57:04