使用M2M关系的自定义模型,.add()
,.create()
和.remove()
被禁用。
目前,我尝试使用.add()
(或其他),并捕获并处理AttributeError
以进行这些自定义M2M关系。
使用Meta
API或其他方式通过模型识别自定义的"官方"方法?在我的处理中的这个阶段,我宁愿通过关系尽可能多地通过关系(而不是很多if m2m_field.related.through == FooBar
语句)
(找到了Django 1.8的解决方案,但我正在开始赏金2.2)
看起来好像
m2m_field.related.through._meta.auto_created is False
做这项工作。
来自django 2.2 .add()
,.create()
等。只要您使用through_defaults
:中间模型的所需字段提供相应的值,方法可以与自定义through
模型一起使用。
来自文档:
您也可以使用add(),create()或set()来创建关系,只要您为任何必需的字段指定taby_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()
方法的行为需要一点关注:
如果由中间模型定义的自定义通过表不使用(model1,model2)对的唯一性,则允许多个值,
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
。
如果我发现任何有趣的东西,我会相应地更新我的答案。
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