通过M2M关系的自定义直通模型,.add()
,.create()
和.remove()
被禁用。
目前,我尝试使用.add()
(或其他)并捕获并处理AttributeError
这些自定义M2M关系。
是否有官员'使用Meta
API或其他方式识别自定义模型的方法?在我处理的这个阶段,我宁愿尽可能一般地通过关系处理所有自定义(而不是很多if m2m_field.related.through == FooBar
语句)
(Django 1.8,但如果有更新版本的解决方案,我们将很快升级。)
答案 0 :(得分:1)
从Django 2.2开始,.add()
,.create()
等方法可以与自定义through
模型一起使用,只要您为中间体的必填字段提供相应的值through_defaults
建立模型:
您还可以使用add(),create()或set()创建关系,只要您为任何必填字段指定through_defaults即可:
>>> beatles.members.add(john, through_defaults={'date_joined': date(1960, 8, 1)}) >>> beatles.members.create(name="George Harrison", through_defaults={'date_joined': date(1960, 8, 1)}) >>> beatles.members.set([john, paul, ringo, george], through_defaults={'date_joined': date(1960, 8, 1)})
您可能希望直接创建中间模型的实例。
.remove()
方法的行为需要引起注意:
如果中间模型定义的自定义穿透表未在(模型1,模型2)对上强制唯一性,允许多个值,则
remove()
调用将删除所有中间模型实例:>>> Membership.objects.create(person=ringo, group=beatles, ... date_joined=date(1968, 9, 4), ... invite_reason="You've been gone for a month and we miss you.") >>> beatles.members.all() <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]> >>> # This deletes both of the intermediate model instances for Ringo Starr >>> beatles.members.remove(ringo) >>> beatles.members.all() <QuerySet [<Person: Paul McCartney>]>
关于_meta
字段,我无法从m2m字段访问它,但是文档的以上部分似乎可以避免访问“ _meta
”的“体操”。 />
如果发现有趣的事情,我将相应地更新答案。
答案 1 :(得分:0)
看起来好像是
m2m_field.related.through._meta.auto_created is False
完成这项工作。
答案 2 :(得分:0)
对于django 2.2,您可以直接检查是否通过模型自动创建
可以通过如下所示的直接检查来确认
# check for the auto_created value
m2m_field.through._meta.auto_created == False
为了对此进行测试,我创建了一些示例分类,其中包含多个M2M字段,一个具有自定义通过字段,一个具有默认类。
from django.db import models
import uuid
class Leaf(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(null=True, max_length=25, blank=True)
# Create your models here.
class MainTree(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
new_leaves = models.ManyToManyField(Leaf, through='LeafTree')
leaves = models.ManyToManyField(Leaf, related_name='main_branch')
class LeafTree(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
tree = models.ForeignKey(MainTree, on_delete=models.CASCADE)
leaf = models.ForeignKey(Leaf, on_delete=models.CASCADE)
测试我们的方法
In [2]: from trees.models import MainTree
In [3]: m = MainTree()
In [4]: m.leaves.through._meta
Out[4]: <Options for MainTree_leaves>
In [5]: m.leaves.through._meta.auto_created
Out[5]: trees.models.MainTree
In [6]: m.new_leaves.through._meta.auto_created
Out[6]: False
In [7]: m.new_leaves.through._meta.auto_created == False
Out[7]: True
In [8]: m.leaves.through._meta.auto_created == False
Out[8]: False