Django REST Filtering Tutorial - Filter with Parameters(Part IV)
Django REST Filtering Tutorial (5 Part Series)
Entrée
We saw in the previous part — django rest filtering tutorial part 3, how to filter against the URL.
$ http :8000/authors/Surname3
# or with curl
# $ curl http://localhost:8000/authors/Surname3
[
{
"first_name": "Name3",
"full_name": "Name3 Surname3",
"id": 3,
"last_name": "Surname3",
"user": 3
}
]
In this post we’ll see how to filter with query params
, like:
# httpie
$ http ":8000/authors/?user=Surname3"
# or with curl
# $ curl http://localhost:8000/authors/?user=Surname3
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 92
Content-Type: application/json
Date: Sat, 14 Apr 2022 10:38:27 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.11
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
[
{
"first_name": "Name3",
"full_name": "Name3 Surname3",
"id": 3,
"last_name": "Surname3",
"user": 3
}
]
Info
You can find usage details of httpie in the first post of this series:
The Code
You can find the code we’re working on this tutorial series in this repository: django-rest-filtering-tutorial
You don’t need to download and setup the repository in order to follow this series, however I’d like to encorauge to do so, since while you play you learn better as always.
User ID
In this section, as an example we’ll filter authors with it’s users'
id/pk
.
# httpie
$ http ":8000/authors/?user=3"
# or with curl
# $ curl http://localhost:8000/authors/?user=3
[
{
"first_name": "Name3",
"full_name": "Name3 Surname3",
"id": 3,
"last_name": "Surname3",
"user": 3
}
]
In order to filter with params, we’re going to override get_queryset
method of our view:
|
|
As we can see, our user param
lies in the query_params
attribute of the
request
object. For more insight, below you can find the related code from
Django Rest Framework’s Github:
|
|
And here is the permalink to it: drf request
You see that it’s just a wrapper
around request.GET
and when you examine
it’s representation you recognise that it’s a QueryDict
object:
>>> from django.http import QueryDict
>>> isinstance(self.request.query_params, QueryDict)
>>> self.request.query_params
>>> <QueryDict: {'user': ['3']}>
Info
class QueryDict
In an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict, a dictionary-like class customized to deal with multiple values for the same key. This is necessary because some HTML form elements, notably , pass multiple values for the same key.
The QueryDicts at request.POST and request.GET will be immutable when accessed in a normal request/response cycle. To get a mutable version you need to use QueryDict.copy().
URLs - Router
Our related urls
/router
to AuthorViewSet looks like below:
|
|
User and Author model
If you want to see the User
and Author
model, you can look at the repo,
however for easy access I put them below as well. In order to examine them just
expand the below section.
User and Author model
User
model:
|
|
Author
model:
|
|
Any Name
As we did in our previous post, let’s filter authors with any name
;
first_name
ofauthor
,last_name
ofauthor
,name
ofuser
,username
ofuser
Modify our get_queryset
to get the desired filtering behavior:
|
|
For this complex filtering we take advantage of Q object with |
(OR
)
logical operator.
One improvement that we can add is that we can check whether given param is in our desired param list:
|
|
With this guard clause we check given paramater is in param_list
, if
not, we return an empty list []
, with Author.objects.none()
.
If you have multiple or more complex filter query paramaters, you should consider to implement Third Party Packages like django-filter which I’ll implement and explain in a later post of this series.
Conclusion
In this tutorial we learned how to filter with query paramaters
with different
set of variations.
See you in the next part of this tutorial series.
All done!