Code

Ticket #3871: 3871.2.diff

File 3871.2.diff, 4.7 KB (added by EspenG <espen@…>, 7 years ago)

Now also support ForeignKeys

Line 
1=== modified file 'django/db/models/fields/related.py'
2--- django/db/models/fields/related.py  2007-04-29 12:33:13 +0000
3+++ django/db/models/fields/related.py  2007-05-01 18:44:40 +0000
4@@ -194,8 +194,9 @@
5     # multiple "remote" values and have a ForeignKey pointed at them by
6     # some other model. In the example "poll.choice_set", the choice_set
7     # attribute is a ForeignRelatedObjectsDescriptor instance.
8-    def __init__(self, related):
9+    def __init__(self, related, manager=None):
10         self.related = related   # RelatedObject instance
11+        self.manager = manager
12 
13     def __get__(self, instance, instance_type=None):
14         if instance is None:
15@@ -206,7 +207,10 @@
16 
17         # Dynamically create a class that subclasses the related
18         # model's default manager.
19-        superclass = self.related.model._default_manager.__class__
20+        if self.manager == None:
21+            superclass = self.related.model._default_manager.__class__
22+        else:
23+            superclass = self.manager.__class__
24 
25         class RelatedManager(superclass):
26             def get_query_set(self):
27@@ -388,17 +392,21 @@
28     # some other model (rather than having a ManyToManyField themselves).
29     # In the example "publication.article_set", the article_set attribute is a
30     # ManyRelatedObjectsDescriptor instance.
31-    def __init__(self, related):
32+    def __init__(self, related, manager=None):
33         self.related = related   # RelatedObject instance
34 
35     def __get__(self, instance, instance_type=None):
36         if instance is None:
37             raise AttributeError, "Manager must be accessed via instance"
38
39         # Dynamically create a class that subclasses the related
40         # model's default manager.
41+
42+        if self.manager == None:
43+            superclass = self.related.model._default_manager.__class__
44+        else:
45+            superclass = self.manager.__class__
46+       
47         rel_model = self.related.model
48-        superclass = rel_model._default_manager.__class__
49         RelatedManager = create_many_related_manager(superclass)
50 
51         qn = backend.quote_name
52@@ -550,7 +558,14 @@
53         setattr(cls, self.name, ReverseSingleRelatedObjectDescriptor(self))
54 
55     def contribute_to_related_class(self, cls, related):
56-        setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
57+        related_accessor_name = related.get_accessor_name()
58+        remote_accessors = related.get_remote_accessors()
59+
60+        setattr(cls, related_accessor_name, ForeignRelatedObjectsDescriptor(related))
61+
62+        # Adding accessors with different managers
63+        for racc in remote_accessors:
64+            setattr(cls, "%s__%s" % (related_accessor_name, racc[0]), ForeignRelatedObjectsDescriptor(related, racc[1]))
65 
66     def formfield(self, **kwargs):
67         defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.all()}
68@@ -723,8 +738,16 @@
69         # m2m relations to self do not have a ManyRelatedObjectsDescriptor,
70         # as it would be redundant - unless the field is non-symmetrical.
71         if related.model != related.parent_model or not self.rel.symmetrical:
72-            # Add the descriptor for the m2m relation
73-            setattr(cls, related.get_accessor_name(), ManyRelatedObjectsDescriptor(related))
74+            related_accessor_name = related.get_accessor_name()
75+            remote_accessors = related.get_remote_accessors()
76+
77+            # Add the descriptor for the m2m relation, using the default manager
78+            # AND keeping backwards compatibility
79+            setattr(cls, related_accessor_name, ManyRelatedObjectsDescriptor(related))
80+
81+            # Addin accessors with different managers
82+            for racc in remote_accessors:
83+                setattr(cls, "%s__%s" % (related_accessor_name, racc[0]), ManyRelatedObjectsDescriptor(related, racc[1]))
84 
85         # Set up the accessors for the column names on the m2m table
86         self.m2m_column_name = curry(self._get_m2m_column_name, related)
87
88=== modified file 'django/db/models/related.py'
89--- django/db/models/related.py 2007-04-29 12:33:13 +0000
90+++ django/db/models/related.py 2007-05-01 17:46:08 +0000
91@@ -19,6 +19,14 @@
92         self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
93         self.var_name = self.opts.object_name.lower()
94 
95+    def get_remote_accessors(self):
96+        d = []
97+        from django.db.models.manager import ManagerDescriptor
98+        for name, attr in self.model.__dict__.items():
99+            if isinstance(attr, ManagerDescriptor):
100+                d.append((name, attr.manager))
101+        return d
102+
103     def flatten_data(self, follow, obj=None):
104         new_data = {}
105         rel_instances = self.get_list(obj)
106
107