| """ |
| By specifying the 'proxy' Meta attribute, model subclasses can specify that |
| they will take data directly from the table of their base class table rather |
| than using a new table of their own. This allows them to act as simple proxies, |
| providing a modified interface to the data from the base class. |
| """ |
| |
| from django.contrib.contenttypes.models import ContentType |
| from django.db import models |
| |
| |
| # A couple of managers for testing managing overriding in proxy model cases. |
| |
| class PersonManager(models.Manager): |
| def get_query_set(self): |
| return super(PersonManager, self).get_query_set().exclude(name="fred") |
| |
| class SubManager(models.Manager): |
| def get_query_set(self): |
| return super(SubManager, self).get_query_set().exclude(name="wilma") |
| |
| class Person(models.Model): |
| """ |
| A simple concrete base class. |
| """ |
| name = models.CharField(max_length=50) |
| |
| objects = PersonManager() |
| |
| def __unicode__(self): |
| return self.name |
| |
| class Abstract(models.Model): |
| """ |
| A simple abstract base class, to be used for error checking. |
| """ |
| data = models.CharField(max_length=10) |
| |
| class Meta: |
| abstract = True |
| |
| class MyPerson(Person): |
| """ |
| A proxy subclass, this should not get a new table. Overrides the default |
| manager. |
| """ |
| class Meta: |
| proxy = True |
| ordering = ["name"] |
| |
| objects = SubManager() |
| other = PersonManager() |
| |
| def has_special_name(self): |
| return self.name.lower() == "special" |
| |
| class ManagerMixin(models.Model): |
| excluder = SubManager() |
| |
| class Meta: |
| abstract = True |
| |
| class OtherPerson(Person, ManagerMixin): |
| """ |
| A class with the default manager from Person, plus an secondary manager. |
| """ |
| class Meta: |
| proxy = True |
| ordering = ["name"] |
| |
| class StatusPerson(MyPerson): |
| """ |
| A non-proxy subclass of a proxy, it should get a new table. |
| """ |
| status = models.CharField(max_length=80) |
| |
| # We can even have proxies of proxies (and subclass of those). |
| class MyPersonProxy(MyPerson): |
| class Meta: |
| proxy = True |
| |
| class LowerStatusPerson(MyPersonProxy): |
| status = models.CharField(max_length=80) |
| |
| class User(models.Model): |
| name = models.CharField(max_length=100) |
| |
| def __unicode__(self): |
| return self.name |
| |
| class UserProxy(User): |
| class Meta: |
| proxy = True |
| |
| class UserProxyProxy(UserProxy): |
| class Meta: |
| proxy = True |
| |
| # We can still use `select_related()` to include related models in our querysets. |
| class Country(models.Model): |
| name = models.CharField(max_length=50) |
| |
| class State(models.Model): |
| name = models.CharField(max_length=50) |
| country = models.ForeignKey(Country) |
| |
| def __unicode__(self): |
| return self.name |
| |
| class StateProxy(State): |
| class Meta: |
| proxy = True |
| |
| # Proxy models still works with filters (on related fields) |
| # and select_related, even when mixed with model inheritance |
| class BaseUser(models.Model): |
| name = models.CharField(max_length=255) |
| |
| class TrackerUser(BaseUser): |
| status = models.CharField(max_length=50) |
| |
| class ProxyTrackerUser(TrackerUser): |
| class Meta: |
| proxy = True |
| |
| |
| class Issue(models.Model): |
| summary = models.CharField(max_length=255) |
| assignee = models.ForeignKey(TrackerUser) |
| |
| def __unicode__(self): |
| return ':'.join((self.__class__.__name__,self.summary,)) |
| |
| class Bug(Issue): |
| version = models.CharField(max_length=50) |
| reporter = models.ForeignKey(BaseUser) |
| |
| class ProxyBug(Bug): |
| """ |
| Proxy of an inherited class |
| """ |
| class Meta: |
| proxy = True |
| |
| |
| class ProxyProxyBug(ProxyBug): |
| """ |
| A proxy of proxy model with related field |
| """ |
| class Meta: |
| proxy = True |
| |
| class Improvement(Issue): |
| """ |
| A model that has relation to a proxy model |
| or to a proxy of proxy model |
| """ |
| version = models.CharField(max_length=50) |
| reporter = models.ForeignKey(ProxyTrackerUser) |
| associated_bug = models.ForeignKey(ProxyProxyBug) |
| |
| class ProxyImprovement(Improvement): |
| class Meta: |
| proxy = True |