django-rest-query-params-filter
pip install django-rest-query-params-filter
Package name: query_params_filter
Resume
A set of classes and methods, built under Python's Django (Rest) Framework, that enable the API consumer to change the query to be executed and get only the wanted objects.
The sample!
In some examples, these classes will be considered, so as the domain "www.example.git".
Nice, also, to know what to import (but soon will be a description just for this).
Filtering fields...
Performing a GET request at www.example.git/users
, considering some fake data, this is what you will receive:
[
{
"id": 1,
"name": "Jourdan",
"age": 18,
"weight": 60.5,
"height": 1.7
},
{
"id": 2,
"name": "Rodrigues",
"age": 21,
"weight": 70,
"height": 1.83
},
{
"id": 3,
"name": "Rodrigues",
"age": 26,
"weight": 58.7,
"height": 1.62
}
]
This is what you get using the pure endpoint. If you perform a GET request with www.example.git/users?name=Jourdan
,
you will get only the following:
[
{
"id": 1,
"name": "Jourdan",
"age": 18,
"weight": 60.5,
"height": 1.7
}
]
Performing a GET request with www.example.git/contacts
, consider the response being the following fake data:
[
{
"user": 1,
"mobile": "55 85 9 9999-9999",
"email": "jourdanrodrigues1@example.git"
},
{
"user": 2,
"mobile": "55 11 9 8888-8888",
"email": "jourdanrodrigues2@example.git"
},
{
"user": 3,
"mobile": "55 67 9 7777-7777",
"email": "jourdanrodrigues3@example.git"
},
]
If you perform a GET request with www.example.git/contacts?email=jourdanrodrigues2@example.git
,
you will get only the following:
[
{
"user": 2,
"mobile": "55 11 9 8888-8888",
"email": "jourdanrodrigues2@example.git"
}
]
And, of course, you can search multiple values and multiple fields.
Request: GET www.example.git/users?name=Jourdan,Rodrigues&age=21
Response:
[
{
"id": 2,
"name": "Rodrigues",
"age": 21,
"weight": 70,
"height": 1.83
}
]
Range queries!
Made it as simple as the multiple values, but using the pipe character (|
). Just one rule: 2 values! If more, will just be ignored.
Request: GET www.example.git/users?age=17|23
Response:
[
{
"id": 1,
"name": "Jourdan",
"age": 18,
"weight": 60.5,
"height": 1.7
},
{
"id": 2,
"name": "Rodrigues",
"age": 21,
"weight": 70,
"height": 1.83
}
]
Distinct values!
Pretty simple aswell: specify the fields you want to be distinct, or just leave empty if you want the entire object.
Note: the empty case is at the database level, not just the fields shown. To ensure getting the distinct fields shown, specify all of them as multiple values (I will find a way to solve this later...).
Empty (distinct database object): GET www.example.git/users?distinct=
Empty (distinct shown object): GET www.example.git/users?distinct=id,name,age,weight,height
Request: GET www.example.git/users?distinct=name
Response:
[
{
"id": 1,
"name": "Jourdan",
"age": 18,
"weight": 60.5,
"height": 1.7
},
{
"id": 2,
"name": "Rodrigues",
"age": 21,
"weight": 70,
"height": 1.83
}
]
Order by values!
At this point, there's almost nothing more to explain: specify the fields you want the query to be ordered by.
Note: you can invert the order by adding a subtraction to the value.
Inverting order: GET www.example.git/users?order_by=-age
Request: GET www.example.git/users?order_by=age
Response:
[
{
"id": 1,
"name": "Jourdan",
"age": 18,
"weight": 60.5,
"height": 1.7
},
{
"id": 2,
"name": "Rodrigues",
"age": 21,
"weight": 70,
"height": 1.83
}
]
Just the quantity of objects...
Well, don't worry... Build the params as you want and put a "quantity=true" up there! :D For the example, I will use the default and the distinct requests:
Default request: GET www.example.git/users?quantity=true
Response:
{
"quantity": 3
}
Distinct request: GET www.example.git/users?distinct=name&quantity=true
Response:
{
"quantity": 2
}
Set up a default filter!!
There are situations that you must specify an attribute value to a query. For this, there is the default_filter
option!
In the models sample, there is an example of usage for this, take a look.
In the example, the default filter is specified directly in the query builder, but you can set it as an attribute of the class (named default_filter
, of course). Also, you can set the priority_filter
parameter taking "params" (as default) and "self" as values in the query builder.
Note: DO NOT PERFORM UPDATE
ON ANY OF THE SELF DICTS, OR THE UPDATES WILL BE APPLIED IN ALL REQUESTS WITH THE CLASS INHERITED!!
Passed a lot of time with my server breaking to figured this out...
Different fields to different queries!
What about the endpoints that you perform various queries, and from each query you use one or more values?
Thought about it too, so I created the selected_fields
option. :)
In the models sample, there is an example of usage for this, take a look.
In the example, the "ad-hoc" method relevant_data
is building the dictionaries to be returned based on the result of 2 queries. Each one took 2 of the 4 fields of the objects list to be returned (but one took an additional field, based on an internal filter).
Show this, but search that!
Happens a lot: lets say you have a field named "full_address" in some model, but you are actually building a custom dictionary, where this field will be shown as just "address"...
You filter it through aliases
option. :)
In the models sample, there is an example of usage for this, take a look.
In the example, the "ad-hoc" method relevant_data
is showing the field "phone", but in the model it exists as "mobile".
So, in the query builder, it was specified through the aliases
parameter that when someone type a value for "phone" in the URL, internally, the query will execute it as "mobile".
As the defaut filter, you are able to set the attribute aliases
in the class.
Understand quickly: aliases = {'field_to_show1': 'field_to_search1', 'field_to_show2': 'field_to_search2'}
Note: DO NOT PERFORM UPDATE
ON ANY OF THE SELF DICTS, OR THE UPDATES WILL BE APPLIED IN ALL REQUESTS WITH THE CLASS INHERITED!!
Passed a lot of time with my server breaking to figured this out...
Different types of values.
Sometimes you may want to put an instance as a value of field to filter in a query.
You should setup a default_filter
dict in the pattern {'pure-field': value_you_want}
. The difference is at the "pure-", which will make the builder create a variable with the value itself inside the namespace used to execute the query.
So, this was created with intent to be used internally and a pure field shall not pass be accessible for URL filtering. I mean, there's no need for it, since these values are always string objects, but if you want to do it anyway, pass the aliases
parameter like aliases = {'your_field': 'pure-your_field'}
.
In the models sample, there is an example of usage for pure values.
Explanation: The user field will be filtered by an user object, but due to the way I did this solution, you have to specify you want to use the object itself to perform the query (promisse I will think about something soon aswell).