在寫作的時候,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