class declaration: order of mixin and class name

If I change

class PostListMixin(PublishedPostsMixin, ListView)

to

class PostListMixin(PublishedPostsMixin, ListView)

it the overriden get_queryset won't work. Can someone explain why?

Sorry You must be a logged in, registered user to answer a question.

Answers

You might want to check out The History of Python: Method Resolution Order by Guido van Rossum. It's a little difficult to digest at first, give it a few reads.

from django.views.generic import ListView
from .models import Post
class PublishedPostsMixin(object):
    def get_queryset(self):
        queryset = super(PublishedPostsMixin, self).get_queryset()
        return queryset.filter(published=True)
class GoodBlogListView(PublishedPostsMixin, ListView):
    model = Post
class BadBlogListView(ListView, PublishedPostsMixin):
    model = Post

In GoodBlogListView, get_queryset() is called first from the PublishedPostsMixin. The first line of PublishedPostsMixin.get_queryset() method calls super() to work it's way up the inheritance chain, aka call the parent's get_queryset() method. In this case that is ListView.get_queryset(). So queryset ends up being the result of ListView.get_queryset(). If you look on the fantastic ccbv.co.uk site, you can inspect ListView's get_queryset() method. Essentially what you will get back is self.model.objects.all(), self.model is the Post model.

Finally, your PublishedPostsMixin.get_queryset() method will return queryset.filter(published=True). Your mixin relies on ListView.get_queryset() to construct the original queryset of which it will then return a filtered version of.

If you reverse the order of inheritance as in BadBlogListView, the first get_queryset() to be run will be from ListView. If you inspect the get_queryset() method for list view you will notice that it does not call super(). Since that get_queryset() method is your first stop in the inheritance chain and it does not call super(), you simply get the result of ListView.get_queryset(). PublishedPostsMixin.get_queryset() is never called.

If you plan on using class-based views, understanding multiple inheritance is a necessity.

I don't see any differences here. Care to expound on this a little more?

sorry, I meant if change it to class PostListMixin(ListView, PublishedPostsMixin), switching the order. I think it has something to do with mro but could you elaborate on it? thanks
Sheldon on