Tricky Django queryset creation, concatenation and

2019-08-14 03:10发布

问题:

I maintain a live chat website (Python2.7, Django 1.5) where any user can set a 'title' statement, and then chat with others under the said title statement via 'public replies'.

I want to produce a 'user activity log' (a queryset), that shows:

1) All title statements produced by the user herself

2) All title statements produced by oneself or someone else, where the user has taken part via 'replies'

3) 1 & 2 concatenated together, and then sorted by how fresh the activity has been in each title statement. E.g. a title statement the user created 2 mins ago would take precedence over one she created 5 mins ago. However a title statement not created by the user, but where she replied 1 min ago, would take precedence over the former title statement she created herself 2 mins ago.

4) Results will be paginated by 15

5) There ought to be no duplicate entries in the resulting queryset. I.e., remove any repeated titles created when (1) and (2) are unioned.

I'm trying to achieve the above in a ListView type class in views.py, inside the get_queryset() method. But can't seem to wrap my head around how to do this. Can anyone help me?

My models.py include:

class Title(models.Model):
    description = models.TextField(validators=[MaxLengthValidator(500)])
    submitter = models.ForeignKey(User)
    submitted_on = models.DateTimeField(auto_now_add=True)
    cagtegory = models.CharField("Category", choices=CATEGS, default=1, max_length=25)
    image_file = models.ImageField(upload_to=upload_to_location, null=True, blank=True )

class Publicreply(models.Model):
    submitted_by = models.ForeignKey(User)
    answer_to = models.ForeignKey(Title)
    submitted_on = models.DateTimeField(auto_now_add=True)
    description = models.TextField(validators=[MaxLengthValidator(250)])
    category = models.CharField("Category", choices=CATEGS, default=1, max_length=20)

In views.py, the relevant code is:

class UserActivityView(ListView):
    model = Title
    slug_field = "username"
    template_name = "user_activity.html"
    paginate_by = 15

    def get_queryset(self):
        username = self.kwargs['slug']
        user = User.objects.filter(username=username)
        title_list1 = Title.objects.filter(submitter=user)
        reply_list = Publicreply.objects.filter(submitted_by=user)
        titles_with_replies = [reply.answer_to.id for reply in reply_list]
        title_list2 = Title.objects.filter(id__in=titles_with_replies)
        title_list3 = (title_list1 | title_list2).order_by('-submitted_on').distinct()
        return title_list3

This solution doesn't work for me because by the time I'm ordering by 'submitted_on', I end up only ordering using title timestamps. That doesn't work because like I stated in requirement (3) above, a title where I posted a reply more recently will take precedence over any title I created less recently. E.g. if I created a title 2 mins ago, a reply I posted 1 min ago on a title I/someone else created 24 hrs ago is still more fresh.

How do I do this? Efficiency is a consideration too. Do ask for more clarity if you feel you need it.