人类已知的唯一方法是使用Metaclass编程。
这里是简短的回答:
from django.db.models.base import ModelBase
class InheritanceMetaclass(ModelBase):
def __call__(cls, *args, **kwargs):
obj = super(InheritanceMetaclass, cls).__call__(*args, **kwargs)
return obj.get_object()
class Animal(models.Model):
__metaclass__ = InheritanceMetaclass
type = models.CharField(max_length=255)
object_class = models.CharField(max_length=20)
def save(self, *args, **kwargs):
if not self.object_class:
self.object_class = self._meta.module_name
super(Animal, self).save(*args, **kwargs)
def get_object(self):
if not self.object_class or self._meta.module_name == self.object_class:
return self
else:
return getattr(self, self.object_class)
class Dog(Animal):
def make_sound(self):
print "Woof!"
class Cat(Animal):
def make_sound(self):
print "Meow!"
和期望的结果:
shell$ ./manage.py shell_plus
From 'models' autoload: Animal, Dog, Cat
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> dog1=Dog(type="Ozzie").save()
>>> cat1=Cat(type="Kitty").save()
>>> dog2=Dog(type="Dozzie").save()
>>> cat2=Cat(type="Kinnie").save()
>>> Animal.objects.all()
[<Dog: Dog object>, <Cat: Cat object>, <Dog: Dog object>, <Cat: Cat object>]
>>> for a in Animal.objects.all():
... print a.type, a.make_sound()
...
Ozzie Woof!
None
Kitty Meow!
None
Dozzie Woof!
None
Kinnie Meow!
None
>>>
它是如何工作的?
有关类 动物的名字
- 存储信息 - 我们使用 object_class为
- 去掉“代理”元属性 - 我们需要在Django( 反向关系,这个坏 方面,我们创造额外DB 表每一个儿童模型和 浪费额外的DB命中为, 好的一面,我们可以添加一些孩子 模型相关字段)
- 自定义保存()动物拯救类 调用保存的对象 的object_class中的名称。
- 方法get_object需要通过在Django 中通过反向关系引用 与名称缓存在 object_class中的Model。
- 做这个.get_object()自动“投射” 每次动物被实例化 重新定义动物的Metaclass 模型。 Metaclass就像一个 类的模板(就像 类是一个对象的模板)。关于元类Python中
的更多信息:http://www.ibm.com/developerworks/linux/library/l-pymeta.html
您可以应用make_sound动物模型,并添加声音= models.charField()到它。 – monkut 2010-02-08 01:22:54
我的例子很简单 - 我想要做的事情需要一堆取决于类型的工作,并且不能与模型一起存储。 – sotangochips 2010-02-08 04:26:23