ChatGPT解决这个技术问题 Extra ChatGPT

How to handle request.GET with multiple variables for the same parameter in Django

In a Django view you can access the request.GET['variablename'], so in your view you can do something like this:

myvar = request.GET['myvar']

The actual request.GET['myvar'] object type is:

<class 'django.http.QueryDict'>

Now, if you want to pass multiple variables with the same parameter name, i.e:

http://example.com/blah/?myvar=123&myvar=567

You would like a python list returned for the parameter myvar, then do something like this:

for var in request.GET['myvar']:
    print(var)

However, when you try that you only get the last value passed in the url i.e in the example above you will get 567, and the result in the shell will be:

5
6
7

However, when you do a print of request.GET it seems like it has a list i.e:

<QueryDict: {u'myvar': [u'123', u'567']}>

Ok Update: It's designed to return the last value, my use case is i need a list.

from django docs:

QueryDict.getitem(key) Returns the value for the given key. If the key has more than one value, getitem() returns the last value. Raises django.utils.datastructures.MultiValueDictKeyError if the key does not exist. (This is a subclass of Python's standard KeyError, so you can stick to catching KeyError QueryDict.getlist(key) Returns the data with the requested key, as a Python list. Returns an empty list if the key doesn't exist. It's guaranteed to return a list of some sort.

Update: If anyone knows why django dev's have done this please let me know, seems counter-intuitive to show a list and it does not behave like one. Not very pythonic!

I think the reasoning is that you should know whether to expect a list or individual value. QueryDict.getitem should not return a list sometimes, an individual item other times - then everyone would always have to check its return type in order to handle it properly.

P
Paolo

You want the getlist() function of the GET object:

request.GET.getlist('myvar')

You may need to add a "[]" to the end of the var name if you are using jquery to post items back.
I knew about getlist but the "[]" threw me. Also, I have a friend named Andy Staple, and for a second I thought he knew way the heck more about Django than I realized. That threw me as well.
This needs to be postered all over the Django docs, the Django Rest Framework docs, and backwards on my forehead. This really caught me off guard
It seems like Django kind of dropped the ball on that one, not sure if intended
F
FallenAngel

Another solution is creating a copy of the request object... Normally, you can not iterate through a request.GET or request.POST object, but you can do such operations on the copy:

res_set = request.GET.copy()
for item in res_set['myvar']:
    item
...

are you sure? this does not change the behavior of the QueryDict at all for me. i just get another QueryDict with the same "limitation"
T
Tomislav Urban

When creating a query string from a QueryDict object that contains multiple values for the same parameter (such as a set of checkboxes) use the urlencode() method:

For example, I needed to obtain the incoming query request, remove a parameter and return the updated query string to the resulting page.

# Obtain a mutable copy of the original string
original_query = request.GET.copy()

# remove an undesired parameter
if 'page' in original_query:
    del original_query['page']

Now if the original query has multiple values for the same parameter like this: {...'track_id': ['1', '2'],...} you will lose the first element in the query string when using code like:

new_query = urllib.parse.urlencode(original_query)

results in...

...&track_id=2&...

However, one can use the urlencode method of the QueryDict class in order to properly include multiple values:

new_query = original_query.urlencode()

which produces...

...&track_id=1&track_id=2&...