在Django中获取最新的不同对象

时间:2013-11-05 21:29:04

标签: python django distinct tastypie

目前我有一个简单的消息聊天应用程序。

class Person(models.Model):
     user = models.OneToOneField(User, primary_key=True)
     sex = models.CharField(max_length=1, null=True, blank=True)

class Message(models.Model):
     sender = models.ForeignKey(Person, related_name= 'sent')
     recipient = models.ForeignKey(Person, related_name = 'received')
     created = models.DateTimeField(auto_now_add=True, null = True, blank = True)
     message = models.CharField(max_length=500)
     conversation_id = models.CharField(max_length = 90)

我使用Django Tastypie作为我的其余API。我想创建一个收件箱,类似于Facebook的收件箱,其中会话按最近的顺序排序。最近的消息对话将显示在收件箱的顶部。

“conversation_id”是发件人的用户名和收件人的用户名。

例如,如果用户Kyle向用户Alex发送消息,则conversation_id将为“alexkyle”。

如果亚历克斯给凯尔留言,它仍然是“亚历克斯”。如果亚历克斯给Bob发消息,那将是“alexbob”。

我进行了设置,以便conversation_id始终采用该唯一的字母顺序。 conversation_id是我用来区分对话的内容。

我有以下资源:

class MessageResource(ModelResource):
    sender = fields.ForeignKey(PersonResource, 'sender', full =True)
    recipient= fields.ForeignKey(PersonResource, 'recipient', full=True)
    class Meta:
        queryset = Message.objects.all()
        allowed_methods = ['get']
        resource_name = 'message-list'
        fields = ['message', 'sender', 'recipient', 'created', 'id', 'conversation_id', 'username']
        authorization = Authorization()
        authentication = BasicAuthentication()
        include_resource_uri = False

    def get_object_list(self, request):
        return super(MessageResource, self).get_object_list(request).filter(Q(sender__user = request.user) | Q(recipient__user = request.user)).distinct('conversation_id').order_by('conversation_id','-created')

但这有效!它按字母顺序发送数据,而不是最近的最新会话。为了使用distinct,我必须使用order_by。问题是我不希望数据按字母顺序排列。我希望它符合最新的对话。我怎么能这样做呢?

2 个答案:

答案 0 :(得分:3)

你的最后一行应该是这样的

return super(MessageResource, self).get_object_list(request).filter(Q(sender__user = request.user) | Q(recipient__user = request.user)).distinct('conversation_id').annotate(last_created=MAX(created)).order_by('-last_created')

在代码中,我使用了MAX方法,该方法应该使用以下内容导入:

from django.db.models import Max
顺便说一句史蒂夫有点意思! conversation_id对我来说似乎有点问题。

更新1

要对分组使用注释,应调用values或values_list方法:

return super(MessageResource, self).get_object_list(request).filter(Q(sender__user = request.user) | Q(recipient__user = request.user)).values('conversation_id').annotate(last_created=Max(created), distinct=True).order_by('-last_created')

答案 1 :(得分:2)

嗯,你设置会话ID的方式有一个缺陷。 如果您有4个用户,名为alex,alexb,bob和ob,则与alex和bob的对话将与具有alexb和ob的用户具有相同的ID ...

关于你的问题,我不确定。您的查询有点复杂,您希望每Message只获得一个conversation_id,每个Message是对话的最新版本(最大(已创建))。我确实认为你可以通过实际添加Conversation模型(此模型的主键也可以是用户名的串联)和updated字段来简化您的设计。它将更容易管理,并可能允许更便宜的查询。

您的对话模型可以像

一样简单
class Conversation(models.Model):
    id = models.CharField(primary_key=True, max_length=64, blank=False)  # the primary key is a string
    updated = models.DatetimeField(auto_now=True, db_index=True)