|
1 """ |
|
2 By specifying the 'proxy' Meta attribute, model subclasses can specify that |
|
3 they will take data directly from the table of their base class table rather |
|
4 than using a new table of their own. This allows them to act as simple proxies, |
|
5 providing a modified interface to the data from the base class. |
|
6 """ |
|
7 |
|
8 from django.contrib.contenttypes.models import ContentType |
|
9 from django.db import models |
|
10 |
|
11 |
|
12 # A couple of managers for testing managing overriding in proxy model cases. |
|
13 |
|
14 class PersonManager(models.Manager): |
|
15 def get_query_set(self): |
|
16 return super(PersonManager, self).get_query_set().exclude(name="fred") |
|
17 |
|
18 class SubManager(models.Manager): |
|
19 def get_query_set(self): |
|
20 return super(SubManager, self).get_query_set().exclude(name="wilma") |
|
21 |
|
22 class Person(models.Model): |
|
23 """ |
|
24 A simple concrete base class. |
|
25 """ |
|
26 name = models.CharField(max_length=50) |
|
27 |
|
28 objects = PersonManager() |
|
29 |
|
30 def __unicode__(self): |
|
31 return self.name |
|
32 |
|
33 class Abstract(models.Model): |
|
34 """ |
|
35 A simple abstract base class, to be used for error checking. |
|
36 """ |
|
37 data = models.CharField(max_length=10) |
|
38 |
|
39 class Meta: |
|
40 abstract = True |
|
41 |
|
42 class MyPerson(Person): |
|
43 """ |
|
44 A proxy subclass, this should not get a new table. Overrides the default |
|
45 manager. |
|
46 """ |
|
47 class Meta: |
|
48 proxy = True |
|
49 ordering = ["name"] |
|
50 |
|
51 objects = SubManager() |
|
52 other = PersonManager() |
|
53 |
|
54 def has_special_name(self): |
|
55 return self.name.lower() == "special" |
|
56 |
|
57 class ManagerMixin(models.Model): |
|
58 excluder = SubManager() |
|
59 |
|
60 class Meta: |
|
61 abstract = True |
|
62 |
|
63 class OtherPerson(Person, ManagerMixin): |
|
64 """ |
|
65 A class with the default manager from Person, plus an secondary manager. |
|
66 """ |
|
67 class Meta: |
|
68 proxy = True |
|
69 ordering = ["name"] |
|
70 |
|
71 class StatusPerson(MyPerson): |
|
72 """ |
|
73 A non-proxy subclass of a proxy, it should get a new table. |
|
74 """ |
|
75 status = models.CharField(max_length=80) |
|
76 |
|
77 # We can even have proxies of proxies (and subclass of those). |
|
78 class MyPersonProxy(MyPerson): |
|
79 class Meta: |
|
80 proxy = True |
|
81 |
|
82 class LowerStatusPerson(MyPersonProxy): |
|
83 status = models.CharField(max_length=80) |
|
84 |
|
85 class User(models.Model): |
|
86 name = models.CharField(max_length=100) |
|
87 |
|
88 def __unicode__(self): |
|
89 return self.name |
|
90 |
|
91 class UserProxy(User): |
|
92 class Meta: |
|
93 proxy = True |
|
94 |
|
95 class UserProxyProxy(UserProxy): |
|
96 class Meta: |
|
97 proxy = True |
|
98 |
|
99 # We can still use `select_related()` to include related models in our querysets. |
|
100 class Country(models.Model): |
|
101 name = models.CharField(max_length=50) |
|
102 |
|
103 class State(models.Model): |
|
104 name = models.CharField(max_length=50) |
|
105 country = models.ForeignKey(Country) |
|
106 |
|
107 def __unicode__(self): |
|
108 return self.name |
|
109 |
|
110 class StateProxy(State): |
|
111 class Meta: |
|
112 proxy = True |
|
113 |
|
114 # Proxy models still works with filters (on related fields) |
|
115 # and select_related, even when mixed with model inheritance |
|
116 class BaseUser(models.Model): |
|
117 name = models.CharField(max_length=255) |
|
118 |
|
119 class TrackerUser(BaseUser): |
|
120 status = models.CharField(max_length=50) |
|
121 |
|
122 class ProxyTrackerUser(TrackerUser): |
|
123 class Meta: |
|
124 proxy = True |
|
125 |
|
126 |
|
127 class Issue(models.Model): |
|
128 summary = models.CharField(max_length=255) |
|
129 assignee = models.ForeignKey(TrackerUser) |
|
130 |
|
131 def __unicode__(self): |
|
132 return ':'.join((self.__class__.__name__,self.summary,)) |
|
133 |
|
134 class Bug(Issue): |
|
135 version = models.CharField(max_length=50) |
|
136 reporter = models.ForeignKey(BaseUser) |
|
137 |
|
138 class ProxyBug(Bug): |
|
139 """ |
|
140 Proxy of an inherited class |
|
141 """ |
|
142 class Meta: |
|
143 proxy = True |
|
144 |
|
145 |
|
146 class ProxyProxyBug(ProxyBug): |
|
147 """ |
|
148 A proxy of proxy model with related field |
|
149 """ |
|
150 class Meta: |
|
151 proxy = True |
|
152 |
|
153 class Improvement(Issue): |
|
154 """ |
|
155 A model that has relation to a proxy model |
|
156 or to a proxy of proxy model |
|
157 """ |
|
158 version = models.CharField(max_length=50) |
|
159 reporter = models.ForeignKey(ProxyTrackerUser) |
|
160 associated_bug = models.ForeignKey(ProxyProxyBug) |
|
161 |
|
162 class ProxyImprovement(Improvement): |
|
163 class Meta: |
|
164 proxy = True |