Posted: 05 March 2019 | Post By: Jai Singhal | |
26 min read |
Filtering queryset dynamically is something that is very common in use. In this post, we will learn how to dynamically filter the queryset depending on the several filters on top of each other. If you do not have hands-on AJAX, then you should definitely check out this post
The promo GIF of what we will be building is shown below.
There is some initial setup that has to be done before starting the real project.
The directory structure of the following project would be like this, we would need to create some new files for this project.
It is good to have on parent template i.e., base.html that can be extended in other templates. If already have, ignore this step. We will be using Bootstrap4 as our CSS framework and jQuery library as always to remove the burden of writing CSS and JS from scratch.
Setting static path
We gonna need Django rest framework for this project, so you need to install it
And put the rest_framework in your INSTALLED_APPS in settings.py
Feed the data
Since we need a lot of data to get better results after filtering, I suggest to download the data, I have found a dataset on Kaggle. You can download the data from here. After downloading it, copy it to the Django main directory(where manage.py lives)
Create new app named wine
Put the app name in settings.py file.
Create a table for storing the data. Open up your wine/models.py file and create the models with the following columns.
Migrate this table to database.
Now that you have downloaded the data and created a structure to store it, let us import the data from the downloaded CSV. Note that you have copied the wine.csv file in the main directory(where manage.py lives). For any confusion follow the directory structure as shown above.
Open the Django shell
Execute this script to import all the data from the wine.csv file, It will take almost 1-2 minute to import the data of total 6500 rows of entries.
Creating REST API
Let’s now write the business logic of our problem, we will first begin with our serializers, serializers in REST framework work very similarly to Django’s Form and ModelForm classes. If you are new with Django Rest framework, you can brush up some basic from here.
This step is not necessary, but it’s good to know about it. This will customize the default pagination class which we will be using to make our REST API.
Now let’s write our views of this project. It includes two important things that need to be discussed.
This class-based view inherits the ListAPIView, which takes the pagination class which we have created above, and also the serializers class.
In this class, we need to override the get_queryset method which will return the query set.
In the get_queryset method, we will filter the queryset on the basis of query parameters, which we are getting from frontend via AJAX call. For whatever filters, applied by the user, it will check in each if condition, and filter down by the respective pararmeter. Likewise, it will perform filters based on the other query parameters. After it completely gets refined with all the filters, we simply return the filtered query set.
2. AJAX GET methods
All other functional based views help us to get the values to fill in the options of the select box. It is much similar to what we have talked in our previous post. All these functions are kind similar to each other.
For all the FBV and CBV, which we have created just above, let’s now create routes for each of these views. Let’s first include the app url into main urls.py file, this will help to confine all the wine(app) url into a separate urls file. Note that we have given the namespace to the wine url.
Create a new file named urls.py in wine app, which will contains the url path of all the view function and class based views of wine app, which is discussed above. Note that we are assigning name to every essential url paths, these names are going to be used as reverse url template tags in templates.
Now that backend, is ready now, let’s move to frontend part. The wine template extends from base template containing the select form inputs, and table structure with the table headers.
It is important to note that every select input contains attribute of url, which is nothing but the reverse url template tag containing the name of the url, Django matches the url name and return an absolute path reference (a URL without the domain name) matching a given view. You can learn more about this from here.