Search code examples
djangodjango-rest-frameworkdjango-viewsfilteringurl-parameters

Django date range filtering from url parameters returns empty queryset


I'm currently trying to do date range filtering from url parameters with get_queryset on a generics class based view, however I am receiving an empty array after doing date range filtering. It's a bit weird since I can print the queryset, just not able to return it.

url parameter: http://127.0.0.1:8000/budget-filter?budget_date=2023-6-7&budget_end_date=2023-6-13

Below is the views.py

@permission_classes([IsAuthenticated])
class BudgetFilter(generics.ListAPIView):

    serializer_class = BudgetSerializer
    paginator = None
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['budget_category', 'budget_account', 'budget_date', 'budget_end_date']

    def get_queryset(self):

        user = self.request.user.username
        budget_date_url = self.request.GET.get('budget_date', None)
        budget_end_date_url = self.request.GET.get('budget_end_date', None)

        if budget_date_url is not None:
            queryset = BudgetModel.objects.filter(current_user = user).filter(budget_date__gte=budget_date_url, budget_date__lte=budget_end_date_url).values()
            print (queryset)
            return queryset

Below is the serializers.py

class BudgetSerializer(serializers.ModelSerializer):
    class Meta:
        model = BudgetModel
        fields = '__all__'

models.py

class BudgetModel(models.Model):
    budget_description = models.CharField(max_length=150)
    budget_price = models.DecimalField(max_digits=35, decimal_places=2)
    budget_account = models.CharField(max_length=100)
    budget_category = models.CharField(max_length=100)
    budget_currency = models.CharField(max_length=150)
    budget_date = models.DateField(auto_now=False)
    budget_end_date = models.DateField(auto_now=False, blank=True)
    budget_display_date = models.CharField(max_length=15)
    current_user = models.CharField(max_length=200)

Response with print (queryset)

<QuerySet [{'id': 20, 'budget_description': 'adassd', 'budget_price': Decimal('22.00'), 'budget_account': 'Main', 'budget_category': 'Education', 'budget_currency': 'AED', 'budget_date': datetime.date(2023, 6, 10), 'budget_end_date': datetime.date(2023, 6, 10), 'budget_display_date': '10 Jun 2023', 'current_user': 'myname'}]>

I tried using different ways of date range filtering, however __gte and __lte method is the one that seemed to do the trick. Now I am able to print the queryset, just not able to return it from the function.


Solution

  • Well, I do not know about django-filter, but you can use a simple custom filter together with range lookup:

    class BudgetFilter(generics.ListAPIView):
        queryset = BudgetModel.objects.all()
        ...
    
        def filter_queryset(self, queryset):
            user = self.request.user.username
            budget_date_url = self.request.GET.get("budget_date", None)
            budget_end_date_url = self.request.GET.get("budget_end_date", None)
    
            if budget_date_url is not None:
                queryset = BudgetModel.objects.filter(current_user=user).filter(
                    budget_date__range=(budget_date_url, budget_end_date_url)
                )
            return queryset
    

    Maybe you also want to check the existence of both params in order to filter!