如何在 Django 中创建记录一定时间后删除记录?

Kha*_*eza 4 python django django-models celery python-3.x

我正在构建一个具有“故事功能”的应用程序,该功能与 Instagram 的故事功能非常相似,因此我想在创建 24 小时后删除故事。因此,如果一个故事是在 2021 年 1 月 1 日中午 12:00 创建的,我想在 2021 年 1 月 2 日中午 12:00 自动删除它。我使用的是 django3.1

我的型号:

class Story(models.Model):
    user = models.ForeignKey(to=User, on_delete=models.CASCADE)
    text = models.CharField(max_length=200)
    image = models.ImageField(blank=True, null=True)
    video = models.FielField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    expiration_time = models.DateTimeField()
Run Code Online (Sandbox Code Playgroud)

我想在特定的过期时间后删除每条记录。

[过期时间在 post_save 函数中设置]

Wil*_*sem 8

最可靠的方法通常是将过滤和删除项目与每小时/每天/每周运行的任务结合起来。

\n

因此,我们可以检索尚未过期的项目:

\n
from django.db.models.functions import Now\n\nstories = Story.objects.filter(expiration_time__lt=Now())
Run Code Online (Sandbox Code Playgroud)\n

如果您需要经常过滤,为此创建一个管理器\xc2\xa0 [Django-doc]可能会更有趣。

\n
from django.db import models\nfrom django.db.models.functions import Now\n\nclass StoryManager(models.Manager):\n\n    def get_queryset(self, *args, **kwargs):\n        return super().get_queryset(*args, **kwargs).filter(\n            expiration_time__lt=Now()\n        )\n\n\nclass Story(models.Model):\n    # …\n    xpiration_time = models.DateTimeField(db_index=True)\n    \n    objects = StoryManager()
Run Code Online (Sandbox Code Playgroud)\n

db_index=True\xc2\xa0 [Django-doc]部分通常会提高过滤过期对象的性能。

\n

当然,这不会删除元素,它只是不会检索这些元素(因此,如果您在视图中过滤这些元素,那么您将看不到这些元素)。

\n

您可以创建一个定期任务,例如cronjob \xc2\xa0 [wiki],它将每天、每周、每月、每小时运行以删除元素。您可以通过定义管理命令\xc2\xa0 [Django-doc]来做到这一点:

\n
# app_name/management/commands/remove_expired_stories.py\n\nfrom django.core.management.base import BaseCommand\nfrom django.db.models.functions import Now\n\nfrom app_name.models import Story\n\nclass Command(BaseCommand):\n    help = \'Remove expired stories\'\n\n    def handle(self, *args, **options):\n        Story._base_manager.filter(expiration_time__gte=Now()).delete()
Run Code Online (Sandbox Code Playgroud)\n

然后你可以手动运行:

\n
python3 manage.py remove_expired_stories
Run Code Online (Sandbox Code Playgroud)\n

或者您可以安排此任务定期运行。这更加稳健:如果由于某种原因调度程序不再工作,那么过滤仍然会阻止您看到Story过期的 s。它也比为每个故事安排一个过期脚本更简单、更高效,特别是因为如果稍后过期时间发生变化,删除计划项目并重新安排这些项目将非常复杂。

\n