10

I have a Django view that processes a GET request. I want to rebuild the query string to include all variables except for one.

I was initially using list comprehension:

>>> from django.http import QueryDict
>>> q = QueryDict('a=2&b=4&c=test') // <--- make believe this is request.GET
>>> z = QueryDict('').copy()
>>> z.update(dict([x for x in q.items() if x[0] != 'b']))
>>> z.urlencode()

But I believe this may be a better solution:

>>> from django.http import QueryDict
>>> q = QueryDict('a=2&b=4&c=test') // <--- make believe this is request.GET
>>> z = q.copy()
>>> del z['b']
>>> z.urlencode()

Can anyone think of an even better approach?

2 Answers 2

12

Django puts the GET request variables into a dictionary for you, so request.GET is already a QueryDict. You can just do this:

z = request.GET.copy()
del z['a']

Note that dictionaries in python (and django QueryDicts) don't have a del() method, you have to use python's built in del() function. QueryDicts are immutable (but copies of them are not), so you were right to copy it before trying to delete from it. Also, in your last line z.urlencode() returns a string, it doesn't convert z to a url encoded string, so you need to assign it to another variable in order to do something with it later.

Hope that helps

Sign up to request clarification or add additional context in comments.

4 Comments

Yup @danny. Sorry I mistyped the del part. But I just used q to keep the example clear.
Hmm.. what do you mean by your edit? I don't think I use the a variable. But nevertheless, this is just an example.
I was just saying to watch out for the KeyError if you're trying to access request.GET['a'] when someone goes to www.yourwebsite.com instead of www.yourwebsite.com?a=2&b=3 But I guess that's off topic since that's just an example and not your whole view
Ahh. I see what you mean. Thanks!
5

The top approach is definitely as good as it gets. I kept thinking your second (lower) example was your newest one and was thoroughly confused.

I can't even imagine another method unless we start doing stuff we're not supposed todo, like setting the _mutable attribute to False instead of copy().

Note: this is for shits and giggles, don't actually do this

2110003 function calls in 2.117 CPU seconds

def test3(n):
    for i in range(n):
        q = QueryDict('a=2&b=4&c=test') # we could pass the mutable argument here 
        # but normally we wouldn't be constructing the querydict ourselves
        q._mutable = True
        del q['b']
        q.urlencode()

3010003 function calls in 3.065 CPU seconds

 def test1(n):
    for i in range(n):
        q = QueryDict('a=2&b=4&c=test')
        z = q.copy()
        del z['b']
        z.urlencode()

2860003 function calls in 3.388 CPU seconds

def test2(n):
    for i in range(n):
        q = QueryDict('a=2&b=4&c=test')
        z = QueryDict('').copy()
        z.update(dict([x for x in q.items() if x[0] != 'b']))
        z.urlencode()

1 Comment

Just curious: How are you getting those stats?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.