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

时间:2018-07-18 08:40:04

标签: django django-orm

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])

编辑 是否可以获取根据其上一条消息时间排序的客户列表,但queryset还将包含上一条消息值作为另一个字段?

1 个答案:

答案 0 :(得分:2)

您要根据您的评论,根据客户的最新消息订购客户。我们可以通过注释 Customer来实现,然后对注释进行排序:

from dango.db.models import Max

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

一个潜在的问题是对根本没有写任何消息的Customer做什么。在这种情况下,Python中的last_message属性将是NULLNone)。我们可以在nulls_first表达式的nulls_last中用.order_byF进行指定。例如:

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')