跳转到主要内容

为django实现多态模型

项目描述

一个django应用程序,提供了一种简单的方式来检索类型转换回其原始ContentType的模型。

https://travis-ci.org/charettes/django-polymodels.svg?branch=master https://coveralls.io/repos/charettes/django-polymodels/badge.svg?branch=master&service=github

安装

>>> pip install django-polymodels

确保'django.contrib.contenttypes''polymodels'已包含在您的INSTALLED_APPS

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 __str__(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.objects管理器检索类型转换后的实例,只需使用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 并通过在您的模型中定义 CONTENT_TYPE_FIELD 属性来指定 polymodels 应该使用哪个字段。这个字段必须是对 ContentTypeForeignKey

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 以避免不必要的查询和过滤,如果您向其传递一些类。在查询集迭代过程中,通过调用 BasePolymorphicModel.type_cast 将获取的实例转换为它们的正确类型。请注意,这些查找在类创建时被缓存,以避免在每次查询时都进行计算。

作者提示

我了解到已经有不少项目正在处理整个 模型继承类型转换问题,例如 django-polymorphic。然而,我希望以轻量级的方式实现此功能:不使用 __metaclass____init__ 覆盖,尽可能使用 django 的公共 API。最终,这实际上只是从 django-mutant 的处理这种问题的机制中提取出来的,因为我需要一个作为独立应用程序的另一个项目。

贡献

如果您遇到错误或想建议添加新功能,请 提交问题创建拉取请求,其中包含 测试

致谢

项目详情


下载文件

下载适合您平台文件的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源分布

django-polymodels-1.8.0.tar.gz (13.4 kB 查看散列)

上传时间

构建分布

django_polymodels-1.8.0-py2.py3-none-any.whl (11.0 kB 查看散列)

上传时间 Python 2 Python 3

支持