在写作的时候,Django的最新版本是1.2
但是它需要一些额外的元素来工作。
您需要为每个将调用其自己的自定义QuerySet对象的动物模型分配一个自定义models.Manager对象。
基本上,而不是返回Animal
情况下(这是你),SubclassingQuerySet
调用as_leaf_class()
方法来检查项目的模式是Animal
与否 - 如果是,那么就返回它,否则执行它的模型上下文搜索。而已。
#models.py
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.db.models.query import QuerySet
class SubclassingQuerySet(QuerySet):
def __getitem__(self, k):
result = super(SubclassingQuerySet, self).__getitem__(k)
if isinstance(result, models.Model):
return result.as_leaf_class()
return result
def __iter__(self):
for item in super(SubclassingQuerySet, self).__iter__():
yield item.as_leaf_class()
class AnimalManager(models.Manager):
def get_query_set(self): # Use get_queryset for Django >= 1.6
return SubclassingQuerySet(self.model)
class Animal(models.Model):
name = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType, editable=False, null=True)
objects = AnimalManager()
def __unicode__(self):
return "Animal: %s" % (self.name)
def save(self, *args, **kwargs):
if not self.content_type:
self.content_type = ContentType.objects.get_for_model(self.__class__)
super(Animal, self).save(*args, **kwargs)
def as_leaf_class(self):
content_type = self.content_type
model = content_type.model_class()
if model == Animal:
return self
return model.objects.get(id=self.id)
class Sheep(Animal):
wool = models.IntegerField()
objects = AnimalManager()
def __unicode__(self):
return 'Sheep: %s' % (self.name)
测试:
>>> from animals.models import *
>>> Animal.objects.all()
[<Sheep: Sheep: White sheep>, <Animal: Animal: Dog>]
>>> s, d = Animal.objects.all()
>>> str(s)
'Sheep: White sheep'
>>> str(d)
'Animal: Dog'
>>>
检出[django-polymorphic](https://github.com/chrisglass/django_polymorphic),它是为此用例而设计的。它也适用于通过外键,ManyToManyFields等获取模型。 – vdboor 2013-05-21 14:15:09
不要这样做! :P请参阅以下内容:http://stackoverflow.com/a/20353347/539490 – AJP 2013-12-03 14:11:36