How to set/get a list type query param in Django Rest Framework

LucyEun
2 min readDec 1, 2020

--

When constructing a GET request, we can set query parameters to send additional information. Setting a string, number, or boolean type query param is relatively simple, but setting a list type query param can be tricky.

Django Request Classes and Query Parameters

When a page is requested, Django creates a http.request.HttpRequest object to store metadata about the request. With a HttpRequest object, you can call .GET to get query parameters. Often in API views, the HttpRequest object is wrapped in a rest_framework.request.Request instance. Request is a wrapper class that allows enhancing a standard HttpRequest instance. On a Request object, you can call .query_params to get query parameters.

typeof(request)
=> rest_framework Request
typeof(request._request)
=> http HttpRequest
request.query_params
=> ...
request._request.GET
=> ...

HttpRequest uses QueryDict to store query params. Hence, accessing each query param can be done the same way we access values in dictionaries.

request.query_params['id'] = 134       #number
request.query_params['name'] = 'hello' #string
request.query_params['remove'] = true #boolean

Accessing a list type query parameter is tricky, as there can be different ways frontend libraries encode list type parameters. QueryDict class provides .setlist() and .getlist() to handle list type query parameters that are encoded by some common javascript libraries including JQuery and Axios.

// Javascript
const query_params = {
list_param: [1, 2, 3],
}
// url encoding through JQuery(>=1.4) and Axios
http://base_url/?list_param[]=1&list_param[]=2&list_param[]=3

# Django
request.query_params.getlist('list_param[]')
=> [1, 2, 3]

When url encoding needs to happen on the Django side, using .setlist() of QueryDict class, django.utils.http.urlencode() and urllib.parse.urlencode all support the same encoding pattern. When using urllib.parse.urlencode just pass doseq=True .

qd = Querydict()
qd.setlist('param[]', [1, 3, 4])
qd.urlencode()
=> 'param[]=1&param[]=3&param[]=4'
from urllib.parse import urlencode
query_dict = {'param[]': [1, 3, 4]}
urlencode(query_dict, doseq=True)
=> 'param[]=1&param[]=3&param[]=4'

Other ways to encode/decode list type query params

One way people might try encoding list type query param is by using the same way other types (string, number, boolean) get encoded. With this pattern, you can get the query parameter the same way other parameters are accessed in Django, but the value gets returned as a string type, so you may need to do additional processing to get the list type.

"http://base_url/?list_param=[1,2,3]"# Django
request.query_params['list_param']
=> "[1, 2, 3]"

JQuery≥1.4 appends [] at the end of the keys of the list type params to allow object recursive encoding. This can be disabled by passing traditional=true argument to the encoding function.

$.param({param: [1, 2, 3]})
=> 'param[]=1&param[]=3&param[]=4' // >= 1.4
$.param({param: [1, 2, 3]}, true) //setting traditional arg = true
=> 'param=1&param=3&param=4' // <= 1.3.2
"http://base_url?list_param=1&list_param=2&list_param=3"#Django
request.query_params.getlist(list_param)
=> [1, 2, 3]

TLDR:

Use Axios and post 1.4 JQuery url encoding, which encodes params into

const query_params = {
list_param: [1, 2, 3],
}
// url encoding through JQuery and Axios
http://base_url/?list_param[]=1&list_param[]=2&list_param[]=3

Use .getlist() function to access list type query params in Django

request.query_params.getlist('list_param[]')
=> [1, 2, 3]

Reference

https://stackoverflow.com/questions/30106783/django-get-query-parameter-list

https://api.jquery.com/jquery.param/

--

--

LucyEun
LucyEun

No responses yet