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 Requesttypeof(request._request)
=> http HttpRequestrequest.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¶m[]=3¶m[]=4'from urllib.parse import urlencode
query_dict = {'param[]': [1, 3, 4]}
urlencode(query_dict, doseq=True)
=> 'param[]=1¶m[]=3¶m[]=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¶m[]=3¶m[]=4' // >= 1.4$.param({param: [1, 2, 3]}, true) //setting traditional arg = true
=> 'param=1¶m=3¶m=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