Chain filter problem in django

157 views
Skip to first unread message

Mohsen Tamiz

unread,
May 10, 2018, 6:45:35 AM5/10/18
to Django users
I have written some questions in stackoverflow 1, 2 and in django rest framework group to get a solution to my problem but still frusterated.
The problem is about having three tables that have a relation sequentialy between each other. More specifically table Person has a reverse relation with table PersonSession and the second one has a reverse relation with Billing table. And the problem arises when we want to filter some persons based on their sessions and their billings.
Three models are as below:

#models.py
    class Person(models.Model):
        first_name = models.CharField(max_length=
20)
        last_name = models.CharField(max_length=20)
   
    class PersonSession(models.Model):
        start_time = models.DateTimeField(auto_now_add=True)
        end_time = models.DateTimeField(null=True,
                                        blank=True)
        person = models.ForeignKey(Person, related_name='sessions')
   
    class Billing(models.Model):
        DEBT = 'DE'
        BALANCED = 'BA'
        CREDIT = 'CR'
   
        session = models.OneToOneField(PersonSession,
                                       blank=False,
                                       null=False,
                                       related_name='billing')
        STATUS = ((BALANCED, 'Balanced'),
                  (DEBT, 'Debt'),
                  (CREDIT, 'Credit'))
   
        status = models.CharField(max_length=2,
                                  choices=STATUS,
                                  blank=False,
                                  default=BALANCED
                                  )

#views.py
    class PersonFilter(django_filters.FilterSet):
        start_time = django_filters.DateFromToRangeFilter(name='sessions__start_time',
                                     distinct=True)
        billing_status = django_filters.ChoiceFilter(name='sessions__billing__status',
                            choices=Billing.STATUS,
                            distinct=True)
   
        class Meta:
            model = Person
            fields = ('first_name', 'last_name')
   
    class PersonList(generics.ListCreateAPIView):
        queryset = Person.objects.all()
        serializer_class = PersonSerializer
        filter_backends = (django_filters.rest_framework.DjangoFilterBackend)
        filter_class = PersonFilter

There is a difference between when we call a simple filter like this:
Person.objects.filter(Q(sessions__start_time__gte='2000-02-01') & \
                      Q(sessions__start_time__lte='2000-03-01') & \
                      Q(sessions__billing__status=Billing.DEBT))
or something like this:
Person.objects.filter(Q(sessions__start_time__gte='2000-02-01') & \ Q(sessions__start_time__lte='2000-03-01')).filter( Q(sessions__billing__status=Billing.DEBT))
As the answer to my question stated the second one creates two inner join on a same table PersonSession that is obviously wrong, but when using djnago-filter, filters on qeryset would be applied sequentially and the result is like the second query which is incorrect.
I hope to find a way to keep my filters working and able to use them together or each of them separately.
Reply all
Reply to author
Forward
0 new messages