django-rest-query-params-filter

Allow your API consumers to make queries through query parameters.


Keywords
url, filter, query, params, python, django, rest_framework
License
Other
Install
pip install django-rest-query-params-filter==1.3.3

Documentation

django-rest-query-params-filter

pip install django-rest-query-params-filter

Package name: query_params_filter

THIS IS SUMMARY!!
Resume The sample! Filtering fields...
Range queries! Distinct values! Order by values!
Just the quantity of objects... Set up a default filter!! Different fields to different queries!
Different types of values.

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).