From 7e0ba90442d362a140957a37ad62457235c1ff54 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Sat, 28 Jan 2006 19:27:51 +0000 Subject: [PATCH] magic-removal: Implemented SingleRelatedObjectDescriptor -- descriptor lookup for many-to-one related lookup, e.g. choice.poll. Old syntax, choice.get_poll(), still works for the moment. git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2148 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/fields/related.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 936ff25287..248a6d8760 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -68,7 +68,28 @@ class SingleRelatedObjectDescriptor(object): # a single "remote" value. # In the example "choice.poll", the poll attribute is a # SingleRelatedObjectDescriptor instance. - pass # Not yet implemented + def __init__(self, field_with_rel): + self.field = field_with_rel + + def __get__(self, instance, instance_type=None): + if instance is None: + raise AttributeError, "%s must be accessed via instance" % self.field.name + else: + cache_name = self.field.get_cache_name() + try: + return getattr(instance, cache_name) + except AttributeError: + val = getattr(instance, self.field.attname) + if val is None: + raise self.field.rel.to.DoesNotExist + other_field = self.field.rel.get_related_field() + if other_field.rel: + params = {'%s__%s__exact' % (self.field.rel.field_name, other_field.rel.field_name): val} + else: + params = {'%s__exact' % self.field.rel.field_name: val} + rel_obj = self.field.rel.to._default_manager.get_object(**params) + setattr(instance, cache_name, rel_obj) + return rel_obj class ManyRelatedObjectsDescriptor(object): # This class provides the functionality that makes the related-object @@ -192,6 +213,12 @@ class ForeignKey(RelatedField, Field): def contribute_to_class(self, cls, name): super(ForeignKey, self).contribute_to_class(cls, name) + + setattr(cls, self.name, SingleRelatedObjectDescriptor(self)) + + # TODO: Delete the rest of this function + # to remove support for old-style related lookup. + # Add methods for many-to-one related objects. # EXAMPLES: Choice.get_poll(), Story.get_dateline() setattr(cls, 'get_%s' % self.name, curry(cls._get_foreign_key_object, field_with_rel=self))