django的多态模型实现
django-polymodels的Python项目详细描述
一个django应用程序,它提供了一种简单的方法来检索类型为casted的模型 到他们原来的ContentType。
安装
>>> pip install django-polymodels
确保'django.contrib.contenttypes'和'polymodels'在 您安装的应用程序
INSTALLED_APPS += ('django.contrib.contenttypes', 'polymodels')
用法
子类PolymorphicModel,一个抽象模型类。
from django.db import models from polymodels.models import PolymorphicModel class Animal(PolymorphicModel): name = models.CharField(max_length=255) def __unicode__(self): return self.name class Mammal(Animal): pass class Dog(Mammal): pass class Reptile(Animal): pass class Snake(Reptile): class Meta: proxy = True
对象的创建方式与通常相同,并且它们的关联ContentType 自动保存:
>>> animal = Animal.objects.create(name='animal') >>> mammal = Mammal.objects.create(name='mammal') >>> reptile = Reptile.objects.create(name='reptile') >>> snake = Snake.objects.create(name='snake')
要从Animal.objectsmanager中检索type casted实例,您只需 必须使用select_subclasses方法。
>>> Animal.objects.select_subclasses() [<Animal: animal>, <Mammal: mammal>, <Reptile: reptile>, <Snake: snake>]
还可以通过将子类的子集作为参数传递给 select_subclass。
>>> Animal.objects.select_subclasses(Reptile) [<Reptile: reptile>, <Snake: snake>]
或者直接从子类管理器。
>>> Reptile.objects.select_subclasses(Snake) [<Snake: snake>]
注意,您还可以通过避免 select_subclasses调用。
>>> Animal.objects.all() [<Animal: animal>, <Animal: mammal>, <Animal: reptile>, <Animal: snake>]
也可以只选择模型的实例 使用exclude_subclasses方法附加管理器。
>>> Mammal.objects.all() [<Mammal: mammal>]
PolymorphicModel的每个实例都有一个type_cast方法,该方法知道如何 将自身转换为正确的ContentType。
>>> animal_snake = Animal.objects.get(pk=snake.pk) <Animal: snake> >>> animal_snake.type_cast() <Snake: snake> >>> animal_snake.type_cast(Reptile) <Reptile: snake>
如果PolymorphicModel.content_type字段与 只需子类的现有字段 polymodels.models.BasePolymorphicModel并指定哪个字段polymodels 应该通过在模型上定义CONTENT_TYPE_FIELD属性来代替。 此字段必须是ForeignKey到ContentType。
from django.contrib.contenttypes.models import ContentType from django.db import models from polymodels.models import BasePolymorphicModel class MyModel(BasePolymorphicModel): CONTENT_TYPE_FIELD = 'polymorphic_ct' polymorphic_ct = models.ForeignKey(ContentType)
工作原理
在引擎盖下select_subclasses调用seleted_related以避免 不必要的查询和filter如果您传递一些类给它。在奎丽斯特 迭代,通过调用 BasePolymorphicModel.type_cast。注意,这些查找是在类上缓存的 创建以避免在每个查询上计算它们。
贡献
如果您碰巧遇到了一个bug或者希望建议添加一个特性 请file an issue或create a pull request包含测试。
学分
- 灵感来源于post of Jeff Elmores。