pythondjango-modelsdjango-viewsdjango-querysetdjango-managers

Custom managers django ... return super().get_queryset().filter(author=user)


How can I do something like this

class FilterManager(models.Manager):
    def get_queryset(self) -> QuerySet:
        user = self.request.user
        return super().get_queryset().filter(author=user)


FILTER1 = FilterManager()
class EventViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.EventSerializer
    queryset = Event.FILTER1.all()

https://docs.djangoproject.com/en/5.0/topics/db/managers/

The documentation and the Internet indicate that only static values of the form can be entered in the "filter" here:

 return super(PublishedManager, self).get_queryset().filter(active=True)

or

get_queryset(self):
    return super().get_queryset().filter(city= 'kolkata')

This is the right thing to do in models.py or is it better to do it in views.py ?

I have a lot of repetitive code right now:

    def get_queryset(self):
        user = self.request.user
        try:
            queryset = Event.objects.filter(author=user)
            return queryset
        except:
            raise Http404  

Solution

  • This is the right thing to do in models.py or is it better to do it in views.py ?

    No, Django's model layer should be request unaware. Indeed, the idea is that models focus on creating, obtaining and aggregating data. Doing this in a useful way and presenting the data to the user is the task of the view layer.

    A Manager has no request, so self.request when using a manager will fail, unless you somehow inject this, but that would make not much sense.

    I have a lot of repetitive code right now.

    You can create a mixin for this. Indeed:

    class MyAuthorViewMixin:
        author_field = 'author'
    
        def get_queryset(self):
            return (
                super()
                .get_queryset()
                .filter(**{self.author_field: self.request.user})
            )

    and then mix this into other views:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    
    class MyListView(LoginRequiredMixin, MyAuthorViewMixin, ListView):
        model = Event

    so you write the logic to filter once, and then just mix it into other views.


    Note: You can limit views to a class-based view to authenticated users with the LoginRequiredMixin mixin [Django-doc].