#25389 closed Bug (fixed)
SimpleLazyObject doesn't pickle correctly when wrapping a Model
Reported by: | Ben Kraft | Owned by: | Ben Kraft |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.8 |
Severity: | Release blocker | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Given a SimpleLazyObject
wrapping an instance of a Django model, if the SimpleLazyObject
has not yet been initialized, pickling it will not correctly save the _django_version
attribute added by 42736ac8. This happens because SimpleLazyObject
's overridden __reduce_ex__
clobbers that of Model, and means that unpickling the pickled object will raise a warning. An example is given here. This is especially relevant given that request.user
is a SimpleLazyObject
wrapping a model instance, so this will happen when pickling an untouched request.user
.
Furthermore, pickling a SimpleLazyObject
wrapping a class which does certain scary things to its __dict__
and overrides __reduce__
can cause an error while pickling. An abstract example is given here. (I don't think that supporting this case is a necessity, but it was how I noticed the above issue, and the attached patch fixes both cases.)
Currently the behavior is effectively to just initialize and then pickle the wrapped object. I have and will attach a patch which does that in a more direct way that works in both of the above cases. It also adds a regression test which covers both of the above cases.
Change History (10)
comment:1 by , 9 years ago
Has patch: | set |
---|---|
Status: | new → assigned |
comment:2 by , 9 years ago
Component: | Uncategorized → Database layer (models, ORM) |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:3 by , 9 years ago
For what it's worth, I've now realized that you don't actually need to do terrifying things to __dict__
to get the actual error; you just have to keep a reference to a model instance as a property on the instance. I've added an example to the gist here; again Foo
here simulates a model. In any case, the fix still works.
comment:4 by , 9 years ago
Severity: | Normal → Release blocker |
---|
This is a regression in 1.8 according to #25426.
comment:6 by , 9 years ago
Patch needs improvement: | unset |
---|
Patch is in https://github.com/django/django/pull/5276. I ran
utils_tests.test_lazyobject
in both python 2 and python 3.