跳转到主要内容

Django扩展,允许将模型“集群”作为一个单独的单位进行工作,独立于数据库

项目描述

如果你有一个这样的数据模型

class Band(models.Model):
    name = models.CharField(max_length=255)

class BandMember(models.Model):
    band = models.ForeignKey('Band', related_name='members', on_delete=models.CASCADE)
    name = models.CharField(max_length=255)

你 wouldn't it be nice if you could construct bundles of objects like this, independently of the database

beatles = Band(name='The Beatles')
beatles.members = [
    BandMember(name='John Lennon'),
    BandMember(name='Paul McCartney'),
]

Unfortunately, you can’t. Objects need to exist in the database for foreign key relations to work

IntegrityError: null value in column "band_id" violates not-null constraint

But what if you could? There are all sorts of scenarios where you might want to work with a ‘cluster’ of related objects, without necessarily holding them in the database: maybe you want to render a preview of the data the user has just submitted, prior to saving. Maybe you need to construct a tree of things, serialize them and hand them off to some external system. Maybe you have a workflow where your models exist in an incomplete ‘draft’ state for an extended time, or you need to handle multiple revisions, and you don’t want to redesign your database around that requirement.

django-modelcluster 扩展了 Django 的外键关系,使其成为可能。它引入了一种新的关系类型,即 ParentalKey,在这种关系下,相关模型被存储在父模型的本地,直到父模型被明确保存。在此之前,可以通过 QuerySet API 的子集访问相关模型。

from modelcluster.models import ClusterableModel
from modelcluster.fields import ParentalKey


class Band(ClusterableModel):
    name = models.CharField(max_length=255)

class BandMember(models.Model):
    band = ParentalKey('Band', related_name='members', on_delete=models.CASCADE)
    name = models.CharField(max_length=255)


>>> beatles = Band(name='The Beatles')
>>> beatles.members = [
...     BandMember(name='John Lennon'),
...     BandMember(name='Paul McCartney'),
... ]
>>> [member.name for member in beatles.members.all()]
['John Lennon', 'Paul McCartney']
>>> beatles.members.add(BandMember(name='George Harrison'))
>>> beatles.members.count()
3
>>> beatles.save()  # only now are the records written to the database

有关更多示例,请参阅单元测试。

多对多关系

对于多对多关系,提供了一个相应的 ParentalManyToManyField

from modelcluster.models import ClusterableModel
from modelcluster.fields import ParentalManyToManyField

class Movie(ClusterableModel):
    title = models.CharField(max_length=255)
    actors = ParentalManyToManyField('Actor', related_name='movies')

class Actor(models.Model):
    name = models.CharField(max_length=255)


>>> harrison_ford = Actor.objects.create(name='Harrison Ford')
>>> carrie_fisher = Actor.objects.create(name='Carrie Fisher')
>>> star_wars = Movie(title='Star Wars')
>>> star_wars.actors = [harrison_ford, carrie_fisher]
>>> blade_runner = Movie(title='Blade Runner')
>>> blade_runner.actors.add(harrison_ford)
>>> star_wars.actors.count()
2
>>> [movie.title for movie in harrison_ford.movies.all()]  # the Movie records are not in the database yet
[]
>>> star_wars.save()  # Star Wars now exists in the database (along with the 'actor' relations)
>>> [movie.title for movie in harrison_ford.movies.all()]
['Star Wars']

请注意,ParentalManyToManyField 定义在父模型上,而不是相关模型上,就像标准的 ManyToManyField 一样。此外,请注意,相关对象(例如上面示例中的 Actor 实例)在关联到父记录之前必须存在于数据库中。(ParentalManyToManyField 允许在写入数据库之前将电影和演员之间的关系存储在内存中,但不包括 Actor 记录本身。)

内省

如果您需要找出父模型上存在的所有子关系(例如,创建模型及其所有子级的深拷贝)- 使用 modelcluster.models.get_all_child_relations 函数。

>>> from modelcluster.models import get_all_child_relations
>>> get_all_child_relations(Band)
[<RelatedObject: tests:bandmember related to band>, <RelatedObject: tests:album related to band>]

这包括定义在父模型任何超类上的关系。

要检索父模型上定义的所有 ParentalManyToManyField 的列表,请使用 modelcluster.models.get_all_child_m2m_relations

>>> from modelcluster.models import get_all_child_m2m_relations
>>> get_all_child_m2m_relations(Movie)
[<modelcluster.fields.ParentalManyToManyField: actors>]

项目详情


下载文件

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

源分发

django-modelcluster-6.3.tar.gz (28.9 kB 查看哈希值)

上传时间

构建分发

django_modelcluster-6.3-py2.py3-none-any.whl (29.0 kB 查看哈希值)

上传时间 Python 2 Python 3

支持者