【问题标题】:Is there a way of a inserting blank datetimefield from another table?有没有办法从另一个表中插入空白日期时间字段?
【发布时间】:2020-08-19 04:14:19
【问题描述】:
class Customer(models.Model):

    last_purchase = models.DateTimeField(blank=True, null=True)

我有一个空白的 DateTimeField,它会用相应表中最后修改的 DateTimeField 不断更新自己。

class Order(models.Model):
    customer = models.ForeignKey(Customer, null=True, on_delete= models.SET_NULL)
    date_created = models.DateTimeField(auto_now_add=True, null=True)


这将如何看待视图?

【问题讨论】:

  • 您的Order 是否有ForeignKeyCustomer
  • 是的,确实如此。我会更新的

标签: python django model


【解决方案1】:

不要重复数据。存储相同的数据或数据聚合通常是一种反模式。事实证明,保持数据同步比人们预期的要难。这意味着如果Order 被创建、更新、删除或从Customer 更改,您必须更新相关的Customer。很容易忽略一些情况,导致不一致。

通常更好的是使用.annotate(..) 来注释您的查询集。因此,如果您从客户那里删除了last_purchase 字段,并且Order 对客户有一个ForeignKey

class Customer(models.Model):
    # …

class Order(models.Model):
    date_created = models.DateTimeField(auto_now_add=True)
    customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)

然后我们可以创建一个QuerySet,看起来像:

from django.db.models import Max

Customer.objects.annotate(
    last_purchase=Max('order__date_created')
)

如果Customer 没有下任何订单,这将是None (NULL)。

如果你经常需要这个,你可以在Manager中定义逻辑:

from django.db import models
from django.db.models import Max

class CustomerManager(models.Manager):

    def get_queryset(self):
        return super().get_queryset(*args, **kwargs).annotate(
            last_purchase=Max('order__date_created')
        )

class Customer(models.Model):
    # …
    objects = CustomerManager()

class Order(models.Model):
    date_created = models.DateTimeField(auto_now_add=True)
    customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)

现在它会在您使用Customer.objects 时自动注释对象。

这将使查询看起来像:

SELECT customer.*
       MAX(order.date_created) AS last_purchase
FROM   customer

您当然可以执行额外的过滤。

【讨论】:

  • 感谢您的快速回复,我尝试了查询集,但它给了我一个按升序排列的客户列表,而不是来自订单表的最后记录日期。如果我在使用 CustomerManager() 时尝试迁移,我似乎会收到错误
  • @kamcoder:经理确实需要迁移。删除 last_purchase 字段可能确实会触发迁移。查询集确实会给出一个客户列表,而这些客户会有一个额外的属性.last_purchase,这样就好像他们有一个字段(但它不是字段)。
  • 谢谢,有没有办法知道 last_purchase 如何从每个客户的订单中返回最新的日期时间字段?
  • @kamcoder:是的,您可以使用print(myqueryset.query) 来检查查询集生成的查询,例如print(Customer.objects.all().query)。它将使用数据库中的聚合函数。
  • 检查查询是什么意思?在这种情况下会怎样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
相关资源
最近更新 更多