I've been struggling with dajngo-filter recently. I have 2 models: Book and Author.
class Book(models.Model):
title = models.CharField(max_length=150)
author = models.ForeignKey(Author, on_delete=model.CASCADE)
length = models.PositiveIntegerField()
class Author(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
year_of_birth = models.DateFiled()
So, I'd like to make filter page, where you can find book by it's properties (title, author etc) AND information about author. For example book shorter than 300 pages, which author is beetween 20-25 years old.
In filters.py I have:
import django_filters
from .models import Book, Author
class BookFilter(django_filters.FilterSet):
class Meta():
model = Book
fields = ['title', 'author']
And have actually no idea how to also filter by different model, which is related by ForeignKey to Book model.
I have really little experience with Dajngo, I wonder if it's very complex problem or not. :) Thanks!
Basically there are two important arguments for each filter:
field_name
: The name of the model field to filter on. You can traverse “relationship paths” using Django’s __
syntax to filter fields on a related model. ex, author__last_name
.
lookup_expr
: The field lookup to use when filtering. Django’s __
syntax can again be used in order to support lookup transforms. ex, year__gte
. For full list of field lookups you can use see here: https://docs.djangoproject.com/en/2.2/ref/models/querysets/#field-lookups.
Together, the field field_name
and lookup_expr
represent a complete Django lookup expression. A detailed explanation of lookup expressions is provided in Django’s lookup reference here: https://docs.djangoproject.com/en/2.2/ref/models/lookups/#module-django.db.models.lookups.
With that in mind here is the answer:
import django_filters
from .models import Book, Author
class BookFilter(django_filters.FilterSet):
title = django_filters.CharFilter(field_name='title', lookup_expr='iexact')
author = django_filters.CharFilter(field_name='author__last_name', lookup_expr='iexact')
class Meta():
model = Book
If you want to filter by exact date just add to your BookFilter
class:
date_of_birth = django_filters.DateFilter(field_name='author__date_of_birth', lookup_expr='exact')
However it would make more sense to filter by year of birth (for example to get all the books from authors born between 1980 and 1990). To do that here is what you add to BookFilter
class:
birth_year__gt = django_filters.NumberFilter(field_name='author__date_of_birth', lookup_expr='year__gt')
birth_year__lt = django_filters.NumberFilter(field_name='author__date_of_birth', lookup_expr='year__lt')