-
Notifications
You must be signed in to change notification settings - Fork 0
Matches ~ Quickstart Guide to django filters
A guide on using django-filters with django-tables2. This is a guide on how to add a search bar and filters to a django project, using the library django-filter. For a full guide, find documentation here. It is worth noting that creating filters using django-filters looks much like creating a table using django-tables2.
You can install the library by running pip install django-filters
. Note: If you are reading this after Fall 2023, django-filters is already in Chigame’s requirements.txt.
Creating Filter Classes
Create a file in your Django app directory (e.g., users, games) named filters.py
. This file will contain filter classes, which correspond to particular models in your Django ORM. The following code block provides an example for the Lobby model in the games app:
import django_filters
from .models import Lobby
class LobbyFilter(django_filters.FilterSet):
class Meta:
model = Lobby
fields = {
‘game’ : [‘icontains’], # 'icontains' is for case-sensitive containment
‘max_players’ : [‘lt’,’gt’], # less than and greater than
}
Meta.fields
is the parameter of interest. Here, ‘game’
is an attribute of the Lobby model, and the corresponding list are the lookup expressions which we want to have for that attribute. These lookup expressions are your filters; you may find a list of them here. Note that you can have multiple filters on one attribute of a model.
Note that Meta.fields is the shortest way to declare a filter, but methods with greater customizability can be found here.
The order of filters in the fields
dictionary affects the order of filters in the generated form. Keep this in mind in case you want to arrange filters in a logical or meaningful order.
Adding Filters to your View
With a FilterSet for a particular model built, we pass those filters to an html page through its view, much like a table. Make sure to import your filters to views.py
from filters.py
, and the FilterView class from django-filters
Continuing with the previous example:
from .filters import LobbyFilter
from django_filters.views import FilterView
…
class LobbyListView(FilterView, SingleTableView):
model = Lobby
table_class = LobbyTable
template_name = "games/lobby_list.html"
filterset_class = LobbyFilter
def get_table_data(self):
self.filter = self.filterset_class(self.request.GET, queryset=super().get_table_data())
return self.filter.qs
We have to override the default get_table_data
method here, which is inherited from SingleTableView
from django-tables2
: this allows us to change the queryset which populates the table to our filtered data.
Function-based views are rather cleaner here. We simply pass the filter in the context of the render statement. For such a hypothetical lobby_list function, this would appear as follows:
def lobby_list(request):
queryset = Lobby.objects.all()
filter = LobbyFilter(request.GET, queryset=queryset)
table = LobbyTable(filter.qs)
return render(request,”games/lobby_list.html”, {'table': table, 'filter': filter})
Handling Multiple Filters
Filters are combined using AND logic by default, which is what results from LobbyFilter(request.Get, queryset=queryset)
. We can adjust this behavior if needed. For example, LobbyFilter(request.Get, queryset=queryset, conjoined=False)
combines filters using OR logic.
Adding Filters to your HTML template
It remains to make the filters accessible from the actual webpage on which our django-tables2
table displays. We need to add a form here, which will be populated by our filters, as well as a submission button to have our chosen filters take their effect. We may also like to add a "clear filters" button to clear all filters, where "?"
allows us to return to the same URL without the queryset. To continue with our example: the filters have been passed to our games/lobby_list.html
page as context under the name filter. We add the following html <form>
above our table (although, it doesn’t matter where this form is added in the html):
<form method="get">
{{ filter.form.as_p }}
<button type="submit">Search</button>
<a href="?">Clear Filters</a>
</form>
{% render_table table %}
In case we need to debug, django-filters automatically performs validation, and error messages can be accessed through {{ filter.form.errors }}
We now have advanced filtering capabilities on our lobbies table.
-
Tournaments
-
Games
-
Matches
-
API
-
Forums
-
Users & Friending