Nasty Django gotcha in my code
Posted by Ian Holsman
So while trying to debug a small problem with bad urls appearing in my code and other things which looked like django or mod_python had some kind of memory leak, I stumbled onto a bug in my code.
The problem I was seeing was that on forms where I create a ‘new’ object details from the previous screen were appearing, and sometimes links were using the previous’s page url were being used instead of the current one.
So after talking to One of the Python Experts, Malcom we narrowed it down to how I was using the ‘extra_context’ parameter being passed into the request.
taking a step back for a second the ‘standard’ way most people set up their urls.py is something like
context= {
'app':'forum',
}
and then define the URL patterns like this example…
urlpatterns += patterns('zilbo.common.tag.views.tag',
(r'^$', 'object_list', { 'queryset': Forum.forum_objects.all(),
'allow_empty':True,
'extra_context': context }),
)
my bug was that I didn’t realize that python passed ‘extra_context’ by reference. and I was blindly assigning things to it in the view itself. (updating the main copy). eg.. my code had something like
extra_context[‘forum’] = forum_obj
so when the next request came on the same thread it would have got a modified context dictionary (instead of the original one). and if my view didn’t actually set that variable (as was the case for the create view) it would take the old version. and would show the details as if it was an edit, not a create.
So the quick-fix in the code at the moment is to just copy() the extra_context where I modify it. and longer term is to treat it as a read-only variable.
hopefully the next djangoite with this problem will find this blog post and save themselves a few grey hairs
This is a common gotcha in Python in general, when passing mutable objects as function parameters. I think the implication that this is a Django gotcha specifically is a bit unfair to Django. Nevertheless, thanks for pointing it out.
Hi Zalman,
your right, it is was due to how python works..
I’m just kicking myself about it thats all