请不要重复数据。存储相同的数据或数据聚合通常是一种反模式。事实证明,保持数据同步比人们预期的要难。这意味着如果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
您当然可以执行额外的过滤。