django扩展,允许将模型的“集群”作为一个单独的单元进行处理,独立于数据库
django-modelcluster的Python项目详细描述
Django ModelCluster
如果您有这样的数据模型:
classBand(models.Model):name=models.CharField(max_length=255)classBandMember(models.Model):band=models.ForeignKey('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'),]遗憾的是,你不能。对象需要存在于数据库中,以使外键关系起作用:
IntegrityError:nullvalueincolumn"band_id"violatesnot-nullconstraint
但如果可以呢?在各种情况下,您可能希望使用相关对象的“集群”,而不必将它们保存在数据库中:可能希望在保存之前呈现用户刚刚提交的数据的预览。也许你需要构建一个事物树,将它们序列化并交给外部系统。也许你有一个工作流程,你的模型在一个不完整的“草稿”状态下存在一个扩展的时间,或者你需要处理多个修改,并且你不想重新设计你的数据库。
django modelcluster扩展django的外键关系以使这成为可能。它引入了一种新的关系类型parentalkey,其中相关的模型被本地存储到“parent”模型,直到显式保存父模型。到目前为止,仍然可以通过QuerySet API的子集访问相关模型:
frommodelcluster.modelsimportClusterableModelfrommodelcluster.fieldsimportParentalKeyclassBand(ClusterableModel):name=models.CharField(max_length=255)classBandMember(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.nameformemberinbeatles.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:
frommodelcluster.modelsimportClusterableModelfrommodelcluster.fieldsimportParentalManyToManyFieldclassMovie(ClusterableModel):title=models.CharField(max_length=255)actors=ParentalManyToManyField('Actor',related_name='movies')classActor(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.titleformovieinharrison_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.titleformovieinharrison_ford.movies.all()]['Star Wars']
注意,ParentalManyToManyField是在父模型而不是相关模型上定义的,就像标准的ManyToManyField一样。还要注意的是,在与父记录关联之前,相关对象-在上述示例中的^ {TT3}$实例必须存在于数据库中。(ParentalManyToManyField允许电影和演员之间的关系存储在内存中,而无需写入数据库,但不允许Actor记录本身。)
内省
如果您需要找出父模型中存在哪些子关系——创建模型及其所有子类的深层副本,则使用^ {TT6}$函数:
>>>frommodelcluster.modelsimportget_all_child_relations>>>get_all_child_relations(Band)[<RelatedObject:tests:bandmemberrelatedtoband>,<RelatedObject:tests:albumrelatedtoband>]
这包括在父模型的任何超类上定义的关系。
要检索父模型上定义的所有parentalmanytomanyfields的列表,请使用modelcluster.models.get_all_child_m2m_relations:
>>>frommodelcluster.modelsimportget_all_child_m2m_relations>>>get_all_child_m2m_relations(Movie)[<modelcluster.fields.ParentalManyToManyField:actors>]