Django

Code

Ticket #7233 (new)

Opened 2 months ago

Last modified 1 week ago

placing request.POST.copy() in session wipes all session values

Reported by: mikechambers Assigned to: nobody
Milestone: Component: django.contrib.sessions
Version: SVN Keywords:
Cc: rajesh.dhawan@gmail.com, dsalvetti@trapeze.com Triage Stage: Accepted
Has patch: 1 Needs documentation: 0
Needs tests: 1 Patch needs improvement: 0

Description (Last modified by ramiro)

Version : (0, 97, 'pre')

The issue is that it appears trying to store a QueryDict? (request.POST, or a copy of a QueryDict?) in the session, will wipe all session data.

You can see the original thread here:

http://groups.google.com/group/django-users/browse_thread/thread/260d9b94f773655e

Basically:

request.session['form_post_data'] = request.POST.copy()
request.session['foo'] = "bar"

Then, in another request:

print request.session.keys()

prints []

(i.e. no keys)

But:

request.session['foo'] = "bar"

then in another request:

print request.session.keys()
prints ['foo']

There seems to be two potential issues:

  1. Cannot store request.POST.copy() or request.POST in the session (should you be able to do this?)
  2. Trying to place request.POST.copy() in the session wipes all session values.

More info on the following threads:

http://groups.google.com/group/django-users/browse_thread/thread/260d9b94f773655e

and

http://groups.google.com/group/django-developers/browse_thread/thread/ec651a3b5f877698

Attachments

sessiontest.zip (11.4 kB) - added by mikechambers on 05/13/08 23:47:09.
test project that reproduces issue
querydict_pickle_fix.diff (1.9 kB) - added by rajesh.dhawan@gmail.com on 05/14/08 13:46:36.
Fix to make copies of QueryDict? instances pickle/unpickle friendly

Change History

05/13/08 23:47:09 changed by mikechambers

  • attachment sessiontest.zip added.

test project that reproduces issue

05/14/08 13:46:36 changed by rajesh.dhawan@gmail.com

  • attachment querydict_pickle_fix.diff added.

Fix to make copies of QueryDict? instances pickle/unpickle friendly

(follow-up: ↓ 4 ) 05/14/08 13:54:00 changed by rajeshdhawan

  • cc set to rajesh.dhawan@gmail.com.
  • needs_better_patch changed.
  • has_patch set to 1.
  • needs_tests changed.
  • needs_docs changed.

The problem is that django.http.QueryDict? instances (even mutable copies of them) do not unpickle properly because the unpickle mechanism does not called init which makes such instances devoid of attributes _mutable and encoding. Without these two attributes pretty much all methods of the resulting instance are unusable. In particular _assert_mutable() crashes and prevents setitem() from working.

The bottom line is that these instances do get pickled and stored into the session but when the session is restored and the object is being unpickled that fails. The session mechanism simply disregards this (rightfully) and returns an empty session dictionary. So no other session data is readable.

I've attached a patch that *hopefully* fixes this. The patch ensures that _mutable and encoding values are saved in the pickled stream and are restored back during unpickling.

(follow-up: ↓ 3 ) 05/14/08 14:10:02 changed by Alex

If I understand it correctly couldn't you just implement __getstate__ and __setstate__ methods on QueryDict?.

(in reply to: ↑ 2 ) 05/14/08 14:15:53 changed by rajeshdhawan

Replying to Alex:

If I understand it correctly couldn't you just implement __getstate__ and __setstate__ methods on QueryDict?.

Normally, that would work. My original attempt to fix this was indeed to implement those methods only to discover that because QueryDict.__setitem__ bombs (on the above mentioned _mutable assert check), __setstate__ fails during unpickling.

(in reply to: ↑ 1 ; follow-up: ↓ 5 ) 05/14/08 15:40:31 changed by mikechambers

Replying to rajeshdhawan:

I just tested the patch, and you can now store a copy of QueryDict? in the session.

This now works:

	request.session['post_copy'] = request.POST.copy()

You cannot place the POST QueryDict? directly into the session like so:

	request.session['post'] = request.POST

I am not sure if that is the intended behavior (although I am guessing it is)

(in reply to: ↑ 4 ) 05/14/08 15:50:05 changed by rajeshdhawan

Replying to mikechambers:

You cannot place the POST QueryDict? directly into the session like so: {{{ request.sessionpost? = request.POST }}} I am not sure if that is the intended behavior (although I am guessing it is)

I think that should be the intended behaviour since request.POST is documented to be immutable. The docs recommend using request.POST.copy() if you need a mutable clone that you can modify (and, I assume, pickle, save in session, restore from session, etc.)

05/14/08 18:47:31 changed by anonymous

  • needs_tests set to 1.

06/14/08 02:14:29 changed by Simon Greenhill

  • stage changed from Unreviewed to Accepted.

06/16/08 11:07:52 changed by ramiro

  • description changed.

06/25/08 14:24:24 changed by djoume

  • cc changed from rajesh.dhawan@gmail.com to rajesh.dhawan@gmail.com, dsalvetti@trapeze.com.

Add/Change #7233 (placing request.POST.copy() in session wipes all session values)




Change Properties
Action