6

I have combine 2 queryset from different models into a list and used pagination to display as a single list.

The problem is the objects from the list are displayed by the pagination according to the models they were created from.

enter image description here

How could I fix the list so when a new object is created from the models. It will be displayed after the recently created object even though the recent object created was from a different models.

Example would be . I have a combine queryset of user's whiteboard and user's comment. If a new whiteboard 's object was created recently and I would create another comment . The comment would be displayed by the pagination after the whiteboard 's object instead of been displayed with all the other comments further down the paginated because it was in a different models

enter image description here

I hope you can get the idea of what i'm trying to achieve :)

Parts of my module

class WhiteBoard(models.Model):

    user = models.ForeignKey(User)
    name = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    picture = models.OneToOneField('Picture',related_name='picture',blank=True,null=True)
    def __unicode__(self):
        return self.name


class Comment(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User)
    body = models.TextField()
    picture = models.ForeignKey(Picture)

views.py

@login_required
def archive(request):
        user = User.objects.get(username=request.user)
        person = Person.objects.get(user=user)
        users = User.objects.filter(pk__in=person.following.all().values_list('user__pk',flat=True))
        picture = whiteboard .objects.filter(user__in=users).order_by("-created")
        comment = Comment.objects.filter(user__in=users).order_by("-created")
        posts= list(chain(picture,comment))
        paginator = Paginator(posts, 5)

        try: page = int(request.GET.get("page", '1'))
        except ValueError: page = 1

        try:
            posts = paginator.page(page)
        except (InvalidPage, EmptyPage):
            posts = paginator.page(paginator.num_pages)
        return render(request,'archive.html',{'picture':picture,'comment':comment,'posts':posts})

archive.html

{% for post in posts.object_list %}

{{post.name }}
<br>
{{post.body}}
{% endfor %}

        <!-- Next/Prev page links  -->
        {% if posts.object_list and posts.paginator.num_pages > 1 %}
        <div class="pagination" style="margin-top: 20px; margin-left: -20px; ">
            <span class="step-links">
                {% if posts.has_previous %}
                        <a href= "?page={{ posts.previous_page_number }}">newer entries &lt;&lt; </a>
                {% endif %}

                    <span class="current">
                    &nbsp;Page {{ posts.number }} of {{ posts.paginator.num_pages }}
                </span>

            {% if posts.has_next %}
                    <a href="?page={{ posts.next_page_number }}"> &gt;&gt; older entries</a>
            {% endif %}
        </span>
    </div>
    {% endif %}

</div>
ferrangb
  • 2,012
  • 2
  • 20
  • 34
donkeyboy72
  • 1,883
  • 10
  • 37
  • 55
  • @catherine Im just mucking around with the combination :) – donkeyboy72 Mar 24 '13 at 09:28
  • @catherine I'm trying to add a font into the cart of your said it and i got this error could not convert string to float: – donkeyboy72 Mar 24 '13 at 09:36
  • I don't know if this will help, it sorted the data. http://stackoverflow.com/questions/431628/how-to-combine-2-or-more-querysets-in-a-django-view – catherine Mar 24 '13 at 09:42
  • @catherine I was on that site yesterday . I learnt how to combine 2 queryset together – donkeyboy72 Mar 24 '13 at 09:49
  • @catherine You created that site within 3 month with jquery javascript?css – donkeyboy72 Mar 24 '13 at 09:52
  • @catherine it's okay . I'm nearly on the edge of solving this problem :] – donkeyboy72 Mar 24 '13 at 10:41
  • @catherine but you gave me that link . I was browsing that topic yesterday and I never though it was any use to my problem but you made me look twice :D – donkeyboy72 Mar 24 '13 at 11:48
  • @catherine If your not busy , could you help me answer this yes or no question . Do you remember the time when you help reverse an upload picture page back to the original board? Is their a way to reverse back to a specific page with pagination /?page=2 – donkeyboy72 Mar 24 '13 at 12:01
  • @catherine Like is it possible? – donkeyboy72 Mar 24 '13 at 12:01
  • page=2 only? no changes? yes it's possible. I remember someone ask the question before and I forgot the name of that guy who answer the question. – catherine Mar 24 '13 at 12:16
  • I give you that link because I saw the sorting process so maybe it can help you. Frankly, I really don't understand totally the combining :) – catherine Mar 24 '13 at 12:19
  • @catherine I mean their /?page=1 /?page=2 /?page=3 . Example Do you remember the page that display all my picture. I implemented a comment feature per picture . When I implemented the pagination . I couldn't reverse back to the normal page because the pages are now /?page=3 , /?page=2 . Is it possible to reverse back to a specific page? – donkeyboy72 Mar 24 '13 at 12:20
  • yes, you can do a trick – catherine Mar 24 '13 at 12:22
  • Sorry if I can't concentrate here. I'm busy posting in my blog. Have so many ideas – catherine Mar 24 '13 at 12:24
  • my boss bought the 2 latest books. I learn a lot. – catherine Mar 24 '13 at 12:29

1 Answers1

9

You just need to sort your list of combined querysets by the created attribute they both share:

from itertools import chain
...
posts = list(
            sorted(
                chain(picture,comment),
                key=lambda objects: objects.created,
                reverse=True  # Optional
            ))
paginator = Paginator(posts, 5)
...

Here's a similar question on the topic

Community
  • 1
  • 1
Timmy O'Mahony
  • 53,000
  • 18
  • 155
  • 177
  • I was browsing that topic yesterday to combine 2 querysets and then I bump into this problem and I looked back and it also answered this question . Timmy , it's sorts from oldest objects to newest object . How can I sort from reverse like newest to oldest? – donkeyboy72 Mar 24 '13 at 11:32
  • Add the keyword `reverse=True`. You can see the updated answer. (Regards the blog; thanks!) – Timmy O'Mahony Mar 24 '13 at 11:36
  • 3
    For what it's worth, if you want to do this lazy style and not have to fetch them all into memory at once - I created a very simple wrapper around queryset.. https://pypi.python.org/pypi/django-compoundqueryset – bwawok Jul 10 '16 at 20:45
  • @bwawok but this combined queryset still doesn't have an `order_by`? That is to say it just orders qs1, then qs2 after, but not ordered with respect to the combined qs1+qs2? – fpghost Jun 13 '19 at 07:05