gpt4 book ai didi

python - 根据 DateTimeField 从数据库中自动删除 Django 对象

转载 作者:行者123 更新时间:2023-12-02 02:28:36 29 4
gpt4 key购买 nike

让我们想象一个带有名称和到期日期的简单食品模型,我的目标是在到达到期日期后自动删除该对象。

我想在到达exp_date后立即从数据库中删除对象(在我的例子中是postgresql),而不是在我的代码中通过exp_date__gt=datetime.datetime.now()进行过滤,然后每隔一段时间执行一次cron/celery脚本通过 exp_date__lt=datetime.datetime.now() 过滤,然后删除

Food(models.Model):
name = models.CharField(max_length=200)
exp_date = models.DateTimeField()

*当通过端点访问对象时,我可以使用普通 View 来完成此操作,甚至可以使用 DRF 来实现,如下所示:

class GetFood(APIView):

def check_date(self, food):
"""
checking expiration date
"""

if food.exp_date <= datetime.datetime.now():
food.delete()
return False

def get(self, request, *args, **kwargs):

id = self.kwargs["id"]

if Food.objects.filter(pk=id).exists():

food = Food.objects.get(pk=id)

if self.check_date(food) == False:
return Response({"error": "not found"}, status.HTTP_404_NOT_FOUND)
else:
name = food.name
return Response({"food":name}, status.HTTP_200_OK)


else:
return Response({"error":"not found"},status.HTTP_404_NOT_FOUND)

但如果没有人尝试通过端点访问该对象,它不会删除该对象。

*我还可以使用一个脚本来设置 cronjob,该脚本会在数据库中查询过期日期小于今天的每个 Food 对象,然后删除它们,甚至设置 Celery。如果我使用 DateField,它确实只需要每天运行一次,但是当我使用 DateTimeField 时,它需要每分钟运行一次(根据纽约项目的需要,每秒运行一次)。

*我还想到了一种奇特的解决方法,使用带有 while 循环的 post_save 信号,如下所示:

@receiver(post_save, sender=Food)
def delete_after_exp_date(sender, instance, created, **kwargs):
if created:
while instance.exp_date > datetime.datetime.now():
pass

else:
instance.delete()

我不知道它是否有效,但似乎效率很低(如果有人可以确认)

瞧,如果您知道一些方法或工具来实现我想做的事情,请提前致谢,感谢您的阅读!

最佳答案

我建议不要删除这些对象,或者至少不能有效地删除这些对象。安排任务很麻烦。即使您设法安排此操作,删除项目的时间也总是会比您安排此操作发生的时间稍晚一些。这也意味着您将每个元素进行一次额外的查询,并且不会批量删除项目。此外,日程安排本质上更加复杂:这意味着您需要一些东西来保存日程安排。如果稍后某些食物的有效期发生变化,则需要额外的逻辑来“取消”当前计划并创建新计划。它还使系统变得不太“可靠”:除了网络服务器之外,还必须运行调度程序守护进程。由于某种原因,守护进程可能会失败,然后您将不再检索未过期的食物。

因此,最好结合过滤记录,以便仅检索未过期的食物,并定期删除已过期的食物。您可以使用以下方法轻松过滤对象:

from django.db.models.functions import <b>Now</b>

Food.objects.filter(<b>exp_date__gt=Now()</b>)

检索未过期的食物。为了提高效率,您可以在exp_date字段上添加数据库索引:

Food(models.Model):
name = models.CharField(max_length=200)
exp_date = models.DateTimeField(<b>db_index=True</b>)

如果您需要经常过滤,您甚至可以使用 Manager [Django-doc] :

from django.db.models.functions import Now

class FoodManager(models.Manager):

def get_queryset(*args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
<b>exp_date__gt=Now()</b>
)

class Food(models.Model):
name = models.CharField(max_length=200)
exp_date = models.DateTimeField(<b>db_index=True</b>)

<b>objects = FoodManager()</b>

现在,如果您使用 Food.objects,您会自动过滤掉所有过期的 Food

此外,您还可以制作一个脚本,例如每天运行以删除已过期的 Food 对象:

from django.db.models import <b>Now</b>

Food._base_manager.filter(exp_date__lte=Now()).delete()

关于python - 根据 DateTimeField 从数据库中自动删除 Django 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65358425/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com