Fixed #24381 -- removed ForeignObjectRel opts and to_opts

These cached properies were causing problems with pickling, and in
addition they were confusingly defined: field.rel.model._meta was
not the same as field.rel.opts.

Instead users should use field.rel.related_model._meta inplace of
field.rel.opts, and field.rel.to._meta in place of field.rel.to_opts.
This commit is contained in:
Anssi Kääriäinen 2015-02-23 09:31:58 +02:00 committed by Tim Graham
parent 78d43a5e10
commit f95122e541
3 changed files with 14 additions and 15 deletions

View File

@ -316,7 +316,7 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
label = field.verbose_name
except AttributeError:
# field is likely a ForeignObjectRel
label = field.opts.verbose_name
label = field.related_model._meta.verbose_name
except FieldDoesNotExist:
if name == "__unicode__":
label = force_text(model._meta.verbose_name)

View File

@ -500,7 +500,7 @@ class SingleRelatedObjectDescriptor(object):
value,
instance._meta.object_name,
self.related.get_accessor_name(),
self.related.opts.object_name,
self.related.related_model._meta.object_name,
)
)
elif value is not None:
@ -1305,14 +1305,6 @@ class ForeignObjectRel(object):
def model(self):
return self.to
@cached_property
def opts(self):
return self.related_model._meta
@cached_property
def to_opts(self):
return self.to._meta
@cached_property
def hidden(self):
return self.is_hidden()
@ -1345,7 +1337,11 @@ class ForeignObjectRel(object):
return self.field.one_to_one
def __repr__(self):
return '<%s: %s.%s>' % (type(self).__name__, self.opts.app_label, self.opts.model_name)
return '<%s: %s.%s>' % (
type(self).__name__,
self.related_model._meta.app_label,
self.related_model._meta.model_name,
)
def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH,
limit_to_currently_related=False):
@ -1396,7 +1392,7 @@ class ForeignObjectRel(object):
# but this can be overridden with the "related_name" option.
# Due to backwards compatibility ModelForms need to be able to provide
# an alternate model. See BaseInlineFormSet.get_default_prefix().
opts = model._meta if model else self.opts
opts = model._meta if model else self.related_model._meta
model = model or self.related_model
if self.multiple:
# If this is a symmetrical m2m relation on self, there is no reverse accessor.
@ -1405,9 +1401,9 @@ class ForeignObjectRel(object):
if self.related_name:
return self.related_name
if opts.default_related_name:
return self.opts.default_related_name % {
'model_name': self.opts.model_name.lower(),
'app_label': self.opts.app_label.lower(),
return opts.default_related_name % {
'model_name': opts.model_name.lower(),
'app_label': opts.app_label.lower(),
}
return opts.model_name + ('_set' if self.multiple else '')

View File

@ -43,6 +43,9 @@ class PickleabilityTestCase(TestCase):
def test_membermethod_as_default(self):
self.assert_pickles(Happening.objects.filter(number4=1))
def test_filter_reverse_fk(self):
self.assert_pickles(Group.objects.filter(event=1))
def test_doesnotexist_exception(self):
# Ticket #17776
original = Event.DoesNotExist("Doesn't exist")