How to filter by request user in Django-filter model

1k Views Asked by At

Im using django-filter package and i want to know how can i pass queryset in ModelChoiceFilter of request user in my django-filter model

I updated with view list and this init functions doesnt have an affect for some reason

filters.py

class PresenceDateFilter(django_filters.FilterSet):

    work_date = DateTimeFromToRangeFilter(
        widget=django_filters.widgets.RangeWidget(
            attrs={'type': 'date', 'class': 'form-control'},
        ))

    class Meta:
        model = PresenceDetailInfo
        fields = ('presence_info__counter_presence',
                  'work_date',
                  )

models.py

class PresenceDetailInfo(models.Model):
    presence_info = models.ForeignKey(PresenceListInfo, default=None, null=True,
                                      on_delete=models.CASCADE, related_name='details_info')

class PresenceListInfo(models.Model):
    counter_presence = models.ForeignKey(CounterParty, default=None, null=True,
                                         on_delete=models.CASCADE)

class CounterParty(models.Model):
    counter_user = models.ManyToManyField(User, blank=True, related_name='counter_user')

views.py

class ShowPresenceInfoList(AccessMixin, ListView):
    model = PresenceDetailInfo
    template_name = 'common/presence_info.html'
    context_object_name = 'details_list'

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(ShowPresenceInfoList, self).get_context_data(**kwargs)
        list_of_dates = PresenceDateFilter(self.request.GET, queryset=self.get_queryset())
        context['form'] = list_of_dates.form
        context['dates'] = list_of_dates.qs

        return context

    def get_queryset(self):
        current_user = self.request.user
        current_counters = CounterParty.objects.filter(counter_user=current_user)

        if current_user.is_superuser:
            qs = PresenceDetailInfo.objects.all().select_related('presence_info', ).order_by(
                'work_date')
        else:
            qs = PresenceDetailInfo.objects.filter(presence_info__counter_presence__in=current_counters).select_related(
                'presence_info', ).order_by('work_date')
        word = PresenceDateFilter(self.request.GET, queryset=qs, request=self.request)
        return word.qs

2

There are 2 best solutions below

6
Pablo On BEST ANSWER

you can pass it in the init inside the class PresenceDateFilter

def __init__(self, data=None, queryset=None, *, request=None, user=None, prefix=None):
        super().__init__(data=data, queryset=queryset, prefix=prefix)
        self.filters['presence_info__counter_presence'].queryset = CounterParty.objects.filter(counter_user=user)

You can customize the query, in the example it will return all the objects in the model and also get the user from request.user.

3
Emerald MagiCoder On

You can modify your view:


    class PresenceListView(ListView):
        model = PresenceDetailInfo
        template_name = 'presence_list.html'
        context_object_name = 'presence_list'
    
        def get_queryset(self):
            queryset = super().get_queryset()
            filter = PresenceDateFilter(
                self.request.GET,
                queryset=queryset,
                request=self.request,  # pass the request object to the filter
            )
            return filter.qs

And then pass the queryset in the init inside the class PresenceDateFilter


    def __init__(self, data=None, queryset=None, *, request=None, prefix=None):
            super().__init__(data=data, queryset=queryset, prefix=prefix)
            if request is not None and request.user.is_authenticated:
                self.filters['presence_info__counter_presence'].queryset = (
                    CounterParty.objects.filter(counter_user=request.user)
                )