我有两个django模型类:
class A(models.Model):
name = models.CharField(max_length = 128) #irrelevant
class B(models.Model):
a = models.ManyToManyField(A)
name = models.CharField(max_length = 128) #irrelevant
我想做的是以下内容:
a1 = A()
a2 = A()
b = B()
b.a.add(a1)
b.a.add(a1) #I want to have a1 twice
b.a.add(a2)
assert len(b.a.all()) == 3 #this fails; the length of all() is 2
我猜add()使用set语义,但我怎么能绕过呢?我试着调查自定义管理器,但我不确定这是否正确(似乎很复杂)......
提前致谢!
答案 0 :(得分:4)
我认为您想要的是使用中间模型使用ManyToManyField中的through
关键字参数来形成M2M关系。有点像上面的第一个答案,但更多的是“Django-y”。
class A(models.Model):
name = models.CharField(max_length=200)
class B(models.Model):
a = models.ManyToManyField(A, through='C')
...
class C(models.Model):
a = models.ForeignKey(A)
b = models.ForeignKey(B)
使用through
关键字时,通常的M2M操作方法不再可用(这意味着add
,create
,remove
或=
的分配运营商)。相反,你必须自己创建中间模型,如下所示:
>>> C.objects.create(a=a1, b=b)
但是,您仍然可以在包含ManyToManyField
的模型上使用常规查询操作。换句话说,以下内容仍然有效:
>>> b.a.filter(a=a1)
但也许更好的例子是这样的:
>>> B.objects.filter(a__name='Test')
只要中间模型上的FK字段未指定为unique
,您就可以使用相同的FK创建多个实例。您还可以通过将您喜欢的任何其他字段添加到C
来附加有关关系的其他信息。
记录中间模型here。
答案 1 :(得分:3)
Django使用关系数据库作为它的底层存储,而且本质上它已经“设置了语义”:没有办法绕过它。因此,如果你想要任何东西的“多组”,你必须用一个数字字段来表示它,它计算每个项目“发生”的次数。 ManyToManyField没有这样做 - 所以,相反,你需要一个单独的Model子类,它明确指出它与之相关的A和B,并且有一个整数属性来“计算多少次”。
答案 2 :(得分:0)
一种方法:
class A(models.Model):
...
class B(models.Model):
...
class C(models.Model):
a = models.ForeignKey(A)
b = models.ForeignKey(B)
然后:
>>> a1 = A()
>>> a2 = A()
>>> b = B()
>>> c1 = C(a=a1, b=b)
>>> c2 = C(a=a2, b=b)
>>> c3 = C(a=a1, b=b)
所以,我们只是:
>>> assert C.objects.filter(b=b).count == 3
>>> for c in C.objects.filter(b=b):
... # do something with c.a