从 Django 中的反向关系获取查询集的不同对象

Getting distinct objects of a queryset from a reverse relation in Django

class Customer(models.Model):
    name = models.CharField(max_length=189)

class Message(models.Model):
    message = models.TextField()
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="messages")
    created_at = models.DateTimeField(auto_now_add=True)

我想在这里做的是,我想获得 Message.created_at 订购的不同客户的查询集。我的数据库是 mysql.

我尝试了以下方法。

qs = Customers.objects.all().order_by("-messages__created_at").distinct()
m = Messages.objects.all().values("customer").distinct().order_by("-created_at")
m = Messages.objects.all().order_by("-created_at").values("customer").distinct()

最后,我用了一套来完成这个,但我想我可能遗漏了一些东西。我目前的解决方案:

customers = set(Interaction.objects.all().values_list("customer").distinct())
customer_list = list()
for c in customers:
    customer_list.append(c[0])

编辑 是否有可能获得根据上次消息时间排序的客户列表,但查询集还将包含上次消息值作为另一个字段?

根据您的评论,您希望根据客户的 最新 消息对其进行排序。我们可以通过 注释 Customer 来做到这一点,然后对注释进行排序:

from dango.db.models import Max

Customer.objects.annotate(
    last_message=Max('messages__crated_at')
).order_by("-last_message")

一个潜在的问题是如何处理 Customer 根本没有写任何消息的人。在这种情况下,last_message 属性将是 Python 中的 NULL (None)。我们可以在 F 表达式的 .order_by 中用 nulls_firstnulls_last 指定它。例如:

from dango.db.models import F, Max

Customer.objects.annotate(
    last_message=Max('messages__crated_at')
).order_by(F('last_message').desc(nulls_last=True))

一个很好的好处是 这个查询集 Customer 对象将有一个额外的属性:.last_message 属性将指定最后一次是什么当用户写了一条消息。

您也可以决定过滤掉它们,例如:

from dango.db.models import F, Max

Customer.objects.filter(
    messages__isnull=False,
).annotate(
    last_message=Max('messages__crated_at')
).order_by('-last_message')