我有两个模型:Play
和PlayParticipant
,定义为(部分):
class PlayParticipant(models.Model):
player = models.ForeignKey('Player')
play = models.ForeignKey('Play')
note = models.CharField(max_length=100, blank=True)
我的一段代码有一个游戏p
,其ID为8581,我想添加参与者。我正在尝试使用RelatedManager的.create()
来执行此操作,例如:
p.playparticipant_set.create(player_id=2383)
Django从中构建:
INSERT INTO `api_playparticipant` (`player_id`, `play_id`, `note`) VALUES (2383, 2383, '')
这是Django中的错误,还是我误用了.create()
?
复制粘贴shell以进行健全性检查:
In [17]: p = Play.objects.get(id=8581)
In [18]: p.id
Out[18]: 8581L
In [19]: p.playparticipant_set.create(player_id=2383)
...
IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`gc/api_playparticipant`, CONSTRAINT `play_id_refs_id_60804ffd462e0029` FOREIGN KEY (`play_id`) REFERENCES `api_play` (`id`))')
来自query.log:
5572 Query INSERT INTO `api_playparticipant` (`player_id`, `play_id`, `note`) VALUES (2383, 2383, '')
答案 0 :(得分:3)
我不知道你的第一个例子怎么会是一个bug?这种行为是完全直观的。您的p是播放,ID为2383,您在其相关集上调用create方法。你还指定了一个名为 player_id 的额外字段,并给它一个2383的值。两个播放id都是2383(因为这是包含这个相关集的播放的id)是合乎逻辑的。并且该玩家ID也将是2383(因为您明确地传递了该值)。
你的第二个例子似乎表明存在错误,但我无法重现它。这是我的模特:
class Player(models.Model):
name = models.CharField(max_length=100)
class Play(models.Model):
title = models.CharField(max_length=100)
class PlayParticipant(models.Model):
player = models.ForeignKey('Player')
play = models.ForeignKey('Play')
note = models.CharField(max_length=100, blank=True)
这是shell输出:
>>> player1 = Player.objects.create()
>>> player2 = Player.objects.create()
>>> player1.id
2
>>> player2.id
3
>>> play1 = Play.objects.create()
>>> play2 = Play.objects.create()
>>> play1.id
3
>>> play2.id
4
>>> pp1 = play1.playparticipant_set.create(player_id=2)
>>> pp1.play.id
3
>>> pp1.player.id
2
无论如何,你为什么要把它发布到SO? Django有一个bugtracker,一些活跃的官方邮件列表和几个IRC频道。
答案 1 :(得分:1)
您应该在Play模型中使用与零个或多个参与者相关的ManyToManyField。在那段代码中你只是在做
play.players.add(player)
答案 2 :(得分:0)
这不是一个错误;检查documentation;特别是关于多对多关系的额外字段的部分。它指定:
与普通的多对多字段不同,您无法使用
add
,create
或assignment
(即beatles.members = [...]
)来创建关系。创建此类关系的唯一方法是创建中间模型的实例。
答案 3 :(得分:0)
我无法重现那种行为。使用类似的模型,我可以运行:
m = Manufacturer.objects.get(1)
p = m.product_set.create(name='23',category_id=1,price=23,delivery_cost=2)
我得到了p
的新Product
实例,其p.manufacturer
外键等于m
。
这是在带有PostgreSQL的Django-1.0.2上;你使用哪个版本的Django,以及哪个SQL后端?
尝试在其中一个上使用两个带有ForeignKey字段的新的最小模型,这应该可行;然后使这些模型逐渐接近表现出失败行为的模型。通过这种方式,您可以隔离使其行为不端的单一变更;这种变化是关键所在。