diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 848fd6e..414f3f6 100644
a
|
b
|
class RelatedField(object):
|
220 | 220 | return self.rel.related_name or self.opts.object_name.lower() |
221 | 221 | |
222 | 222 | class SingleRelatedObjectDescriptor(object): |
223 | | # This class provides the functionality that makes the related-object |
224 | | # managers available as attributes on a model class, for fields that have |
| 223 | # This class provides the functionality that makes the related objects |
| 224 | # (not managers) available as attributes on a model class, for fields that have |
225 | 225 | # a single "remote" value, on the class pointed to by a related field. |
226 | 226 | # In the example "place.restaurant", the restaurant attribute is a |
227 | 227 | # SingleRelatedObjectDescriptor instance. |
… |
… |
class SingleRelatedObjectDescriptor(object):
|
254 | 254 | params = {'%s__pk' % self.related.field.name: instance._get_pk_val()} |
255 | 255 | rel_obj = self.get_query_set(instance=instance).get(**params) |
256 | 256 | setattr(instance, self.cache_name, rel_obj) |
| 257 | # Also cache a back-reference to me on the related object |
| 258 | # (this is only used in one-to-one relations) |
| 259 | if rel_obj: |
| 260 | cache_name = self.related.field.get_cache_name() |
| 261 | if not getattr(rel_obj, cache_name, None): |
| 262 | setattr(rel_obj, cache_name, instance) |
257 | 263 | return rel_obj |
258 | 264 | |
259 | 265 | def __set__(self, instance, value): |
… |
… |
class ReverseSingleRelatedObjectDescriptor(object):
|
409 | 415 | # object you just set. |
410 | 416 | setattr(instance, self.field.get_cache_name(), value) |
411 | 417 | |
| 418 | class CachingReverseSingleRelatedObjectDescriptor(ReverseSingleRelatedObjectDescriptor): |
| 419 | """ |
| 420 | This is a variation on ReverseSingleRelatedObjectDescriptor, which makes sure |
| 421 | a reverse back-reference (which is a forward reference) is cached on the target |
| 422 | of a reverse relation access. This is useful for one-to-one relations, making sure |
| 423 | that if |
| 424 | |
| 425 | class A(model): |
| 426 | pass |
| 427 | class B(model): |
| 428 | a = OneToOneField(A) |
| 429 | a1 = A.objects.get(...) |
| 430 | |
| 431 | then |
| 432 | |
| 433 | a1.b.a is a1 |
| 434 | """ |
| 435 | def __get__(self, instance, instance_type=None): |
| 436 | myclass = CachingReverseSingleRelatedObjectDescriptor # ridiculously long name... |
| 437 | rel_obj = super(myclass, self).__get__(instance, instance_type) |
| 438 | if rel_obj: |
| 439 | cache_name = self.field.related.get_cache_name() |
| 440 | if not getattr(rel_obj, cache_name, None): |
| 441 | setattr (rel_obj, cache_name, instance) |
| 442 | return rel_obj |
| 443 | |
| 444 | |
412 | 445 | class ForeignRelatedObjectsDescriptor(object): |
413 | 446 | # This class provides the functionality that makes the related-object |
414 | 447 | # managers available as attributes on a model class, for fields that have |
… |
… |
class OneToOneField(ForeignKey):
|
1034 | 1067 | kwargs['unique'] = True |
1035 | 1068 | super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs) |
1036 | 1069 | |
| 1070 | def contribute_to_class(self, cls, name): |
| 1071 | # Ancestors do all sorts of stuff |
| 1072 | super(OneToOneField, self).contribute_to_class(cls, name) |
| 1073 | # ... but they choose the wrong implementation for the attribute |
| 1074 | setattr(cls, self.name, CachingReverseSingleRelatedObjectDescriptor(self)) |
| 1075 | |
1037 | 1076 | def contribute_to_related_class(self, cls, related): |
1038 | 1077 | setattr(cls, related.get_accessor_name(), |
1039 | 1078 | SingleRelatedObjectDescriptor(related)) |