1

I'm trying to understand the concept of mixins using the following example:

I have a simple serializer using the DRF:

class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = Test
        fields = ('url', 'name', 'user')

I would like to create a mixin which enhances (overwrites the class get_queryset) for any custom serializer by added a check that the user owns the objects and only shows these items for example...

def get_queryset(self):
        """
        This view should return a list of all the items
        for the currently authenticated user.
        """
        user = self.request.user
        return ???????.objects.filter(user=user)

So my TestSerializer would look like this:

class TestSerializer(serializers.ModelSerializer, UserListMixin):
    etc

and UserListMixin:

class UserListMixin(object):
    """
    Filtering based on the value of request.user.
    """

    def get_queryset(self, *args, **kwargs):
        """
        This view should return a list of all the purchases
        for the currently authenticated user.
        """
        user = self.request.user
        return super([?????????], self).get_queryset(*args, **kwargs).filter(user=user)

What I'm having difficulty with is creating the UserListMixin class. How can I return the correct object based on what I'm extending return [OBJECT].objects.filter(user=user) and would this approach work?

Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
Prometheus
  • 32,405
  • 54
  • 166
  • 302

1 Answers1

2

Filters are chainable, so the best thing to do here is to call the super method to get the default queryset, then add your filter on top:

def get_queryset(self, *args, **kwargs)
    user = self.request.user
    return super(UserListMixin, self).get_queryset(*args, **kwargs).filter(user=user)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Hi Daniel, that makes sense. But in terms of a mixin how can I return super TestSerializer when it could be attached on any serializer? – Prometheus Jul 05 '14 at 10:22
  • That's how subclassing works in Python - `super(class, self)` always calls the next class in the method resolution order, whatever it is. See Raymond Hettinger's article [Super considered super](http://rhettinger.wordpress.com/2011/05/26/super-considered-super/). – Daniel Roseman Jul 05 '14 at 10:27
  • updated OP: UserListMixin. Maybe I'm not understanding this correctly :( – Prometheus Jul 05 '14 at 10:29
  • OK, my mistake, it should be UserListMixin. – Daniel Roseman Jul 05 '14 at 10:30
  • I see, that makes sense now :) So I'm I right in thinking that UserListMixin attached to TestSerializer now overwrites it's get_queryset method? – Prometheus Jul 05 '14 at 10:33
  • 2
    Yes, with one caveat: the mixin needs to be listed first in the inheritance declaration: `class TestSerializer(UserListMixin, serializers.ModelSerializer)`. That's because it's always the *first* method found that is used. – Daniel Roseman Jul 05 '14 at 10:35