pythondjangoselfdjango-filter

Can't access self.request.user when overriding FilterSet.qs


I have written code for a filter that takes into account some fields of a given patient (name, age and id). The users of the website will be doctors, and I want only patients of the current logged in doctor to come up in the search. After reading the docs and trying to do so in many different ways, I have accomplished nothing.

It seems the best method is to override the FilterSet.qs function and so I did, similarly to what is present in the documentation. However, when I try to access self.request.user it comes back as none, even though there is a user currently logged in.

I am new to Django and still trying to figure things out. Any help is highly appreciated. I believe I have pasted in all that is relevant, but I am sorry in advance if something is missing.

# filters.py 

import django_filters
from .models import Patient, Teams
from django import forms
from django.contrib.auth.models import User


class PatientFilter(django_filters.FilterSet):

    id = django_filters.NumberFilter(widget=forms.NumberInput(attrs={ 'min': '1'}))
    age = django_filters.NumberFilter(widget=forms.NumberInput(attrs={ 'min': '0'}))

    class Meta:
        model = Patient

        fields = {
            'first_name' : ['icontains'],
            'age' : ['exact'],
            'id' : ['exact']

        }

    @property
    def qs(self):
        parent = super().qs
        author = getattr(self.request, 'user', None)
        print('Author')
        print(self.request)

        return parent.filter(owner=author)



# views.py

class UserPatientListView(FilterView, ListView):
    model = Patient
    template_name = 'bcctapp/user_patients.html'
    context_object_name = 'patients'
    paginate_by = 2
    filterset_class = PatientFilter

    def get_queryset(self):
        queryset = super().get_queryset()
        self.filterset = self.filterset_class(self.request.GET, queryset=queryset)
        return self.filterset.qs.distinct()

    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter'] = PatientFilter(self.request.GET, queryset = self.get_queryset())
        context['number_results'] = context['filter'].qs.count()
        return context



# models.py

class Patient(models.Model):
    first_name = models.CharField(max_length=100,null=True)
    last_name = models.CharField(max_length=100,null=True)
    age = models.IntegerField(null=True)
    birthday = models.CharField(max_length=100)
    surgery_date = models.CharField(max_length=100)
    patient_height = models.IntegerField(null=True)
    patient_weight = models.IntegerField(null=True)
    bra = models.CharField(max_length=100,null=True)
    date_posted = models.DateTimeField(default=timezone.now)
    owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    n_images = models.IntegerField(null=True)
    team = models.IntegerField(null=True)
    share = models.CharField(validators=[int_list_validator],max_length=100000, null=True)
    # Surgery Type
    C1 = 1
    C2 = 2
    C3 = 3
    M1 = 4
    M2 = 5
    M3 = 6
    M4 = 7
    M5 = 8
    M6 = 9
    M7 = 10

    SURGERY_TYPE_CHOICES = [
        (C1, 'Conservative surgery - unilateral'),
        (C2, 'Conservative surgery with bilateral reduction'),
        (C3, 'Conservative surgery with LD or LICAP / TDAP'),
        (M1, 'Mastectomy with unilateral reconstruction with implant'),
        (M2, 'Mastectomy with unilateral reconstruction with autologous flap'),
        (M3, 'Mastectomy with bilateral reconstruction with implants'),
        (M4,
         'Mastectomy with unilateral reconstruction with implant and contralateral symmetrization with implant (augmentation)'),
        (M5, 'Mastectomy with unilateral reconstruction with implant and contralateral symmetrization with reduction'),
        (M6,
         'Mastectomy with unilateral reconstruction with autologous flap and contralateral symmetrization with reduction'),
        (M7,
         'Mastectomy with unilateral reconstruction with autologous flap and contralateral symmetrisation with implant (augmentation)')
    ]

    surgery_type = models.IntegerField(choices=SURGERY_TYPE_CHOICES)

    def __str__(self):
        return self.first_name

    def get_absolute_url(self):
        return reverse('patient-detail', kwargs={'pk': self.pk})

    def query_set(self,id):
        return Patient(id=id)

Solution

  • In your case, you are trying to filter the base queryset with logged-in user. For that, you don't need the filter set class, just override the get_queryset(...) method

    class UserPatientListView(FilterView, ListView):
        model = Patient
        template_name = 'bcctapp/user_patients.html'
        context_object_name = 'patients'
        paginate_by = 2
        filterset_class = PatientFilter
    
        def get_queryset(self):
            queryset = super().get_queryset().filter(owner=self.request.user)
            return queryset
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['filter'] = PatientFilter(self.request.GET, queryset=self.get_queryset())
            context['number_results'] = context['filter'].qs.count()
            return context