Django filter module: lookup expression (year) does not return the desired queryset

Viewed 138

I am using the django-filter module. I would like to get all objects where the year is 2011 or greater.

this is my setup ...

Actual behaviour:

  • When I enter a year, then I get the error message: "Enter a valid date." and the queryset is unchanged.

  • I tried entering a date instead of the year, but then the whole page fails with the error message Field 'None' expected a number but got datetime.date(2011, 1, 1).

Error Message

The model:

class BaseInvoice(models.Model):
    id = ShortUUIDField(primary_key=True)
    invoive_number = models.CharField(max_length=50)
    invoicing_party_ID = models.ForeignKey(InvoicingParty, on_delete=models.CASCADE)
    invoice_type = models.CharField(
        max_length=2, 
        choices=invoice_type,
        default='IN'
        )
    realestate_id = models.ForeignKey(RealEstate, on_delete=models.CASCADE)
    user_group = models.ForeignKey(Group, on_delete=models.CASCADE)
    year_of_contribution = models.DateField(auto_now=False, auto_now_add=False)
    start_of_period = models.DateField(auto_now=False, auto_now_add=False)
    end_of_period = models.DateField(auto_now=False, auto_now_add=False)
    interval = models.ForeignKey(Interval, on_delete=models.CASCADE, default=0)
    currency = models.ForeignKey(Currency, on_delete=models.CASCADE, default='EUR')
    class Meta:
        abstract = True    
    

class RealEstateTax(BaseInvoice):
    realestate_tax = models.DecimalField(max_digits=20, decimal_places=2)

The Filter

import django_filters
from django_filters import DateFilter

from .models import *

class InvoiceFilter(django_filters.FilterSet):
    
    billing_year = DateFilter(
        label='Abrechnungsjahr',
        field_name='start_of_period', 
        lookup_expr='year__gt'
        )
    
    class Meta:
        model = RealEstateTax
        fields = ['realestate_id', 'billing_year']

The view

from realestate.models import RealEstate
from django.shortcuts import render
from django.http import HttpResponse
from .models import *
from .filters import InvoiceFilter
from django.db.models import Sum

def utilities_bill(request):
    realestate_tax = RealEstateTax.objects.all()
    insurance_invoice = InsuranceInvoice.objects.all()

    raTaxFilter = InvoiceFilter(request.GET, queryset=realestate_tax)
    inFilter = InvoiceFilter(request.GET, queryset=insurance_invoice)
    realestate_tax = raTaxFilter.qs
    insurance_invoice = inFilter.qs
    realestate_sum = realestate_tax.aggregate(Sum('realestate_tax'))['realestate_tax__sum']
    print(request.GET)

    context = {'realestate_tax':realestate_tax, 'insurance_invoice':insurance_invoice, 'raTaxFilter':raTaxFilter, 'realestate_sum':realestate_sum}
    return render(request, 'billing/utilities.html', context)

This is the first part of the template:

{% extends 'main.html' %}
{% load static %}

{% block title %} Utilities Bill {% endblock %}

{% block content %}
<img src="{% static 'media/bojack.png' %}" style="width:100px">
<h1>Nebenkostenabrechnung</h1>
<br>

<div class="container">
    <div class="row">
        <form class="form-group" method="get">
            {{raTaxFilter.form}}
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>
</div>

What I tried so far:

  • Entering an int | --> queryset is unchanged
  • Entering a date | --> Field 'None' expected a number but got datetime.date(2011, 1, 1).
  • tried it with lookup expressions : year, year__gte, year__gt | --> didn't work
  • Tested a filter directly in the view realestate_tax = realestate_tax.filter(start_of_period__year__gte=2011) | --> this works but then it is without the django-filter module and I have to build everything by hand

Many thanks in advance. I hope you can help me out.

1 Answers

Your billing_year is not a DateFilter, but an NumberFilter. Indeed, a year is an integer, not a date. This thus means that we can filter with a given number (for example 2011) on the year of that date:

class InvoiceFilter(django_filters.FilterSet):
    
    billing_year = NumberFilter(
        label='Abrechnungsjahr',
        field_name='start_of_period', 
        lookup_expr='year__gt'
    )
    
    class Meta:
        model = RealEstateTax
        fields = ['realestate_id', 'billing_year']
Related