【问题标题】:Django throws a Foreign Key IntegrityError with a valid ForeignKeyDjango 使用有效的外键抛出外键完整性错误
【发布时间】:2021-09-27 21:48:43
【问题描述】:

我正在 Django 中为多人战舰游戏创建一个项目,我正在尝试设置我的数据库以便记录游戏、玩家和用户操作,这里是 app/model.py 代码

from django.db import models


# Create your models here.
class Player(models.Model):
    username = models.CharField(max_length=10,primary_key=True)
    password = models.CharField(max_length=10)


class GameBoard(models.Model):
    size = models.IntegerField(default=10)
    state = models.CharField(max_length=500,default='')

class Game(models.Model):
    game_id = models.AutoField(primary_key=True)
    player1 = models.ForeignKey(Player,related_name='player1',blank = True,null=True,on_delete=models.SET_NULL)
    player2 = models.ForeignKey(Player,related_name='player2',blank = True,null=True,on_delete=models.SET_NULL)
    board = models.ForeignKey(GameBoard,related_name='game_board',on_delete=models.CASCADE)

    def __str__(self):
        return f'Game: {self.game_id}, player1: {self.player1}, player2: {self.player2}, board {self.board}'

class Action(models.Model):
    GAME_ACTIONS = (
        ('a', 'Attack'),
        ('s', 'Surrender'),
    )
    player_action = models.ForeignKey(Player,related_name='player_action',null=True,on_delete=models.SET_NULL)
    action = models.CharField(max_length=3, choices=GAME_ACTIONS)
    game = models.ForeignKey(Game,related_name='played_in',on_delete=models.CASCADE)

然后我运行 makemigrations 并 migrate 来更新数据库。最后我尝试使用 manage.py shell 测试代码:

from battleship.models import *

p1 = Player('Alice','password1')
p1.save()
p2 = Player('Bob','password')
p2.save()

b = GameBoard()
b.save()

g = Game(player1 = p1,player2 = p2,board = b)
g.save()

当我运行此代码时,我收到以下错误:django.db.utils.IntegrityError: FOREIGN KEY constraint failed。我还尝试保存一个没有玩家的游戏:

g = Game(player1 = None,player2 = None,board = b)
g.save()

前面的代码可以正常执行,我还检查了数据库上保存的对象,它实际上保存正确。

我认为问题出在 p1 和 p2 上,但我不明白为什么,因为 board 也是外键。我假设这取决于 Player 模型中的 null=True ,但是我没有看到该参数存在的问题(如果删除了玩家,我想将现有游戏名称更新为 null 而不是在级联时删除) .

【问题讨论】:

  • 我认为它与Game 模型中的相关名称冲突。您是否尝试更改 player1player2 的相关名称或属性名称本身?
  • 我试过了,似乎有帮助,现在错误是 OperationalError: table Battleship_game has no column named p1_id (是的,我确实在更改后迁移了)
  • 你能发布你更新的模型代码吗?
  • 另外,在上面的示例中,您没有正确创建播放器对象。在创建对象时,您必须使用关键字参数。就像你正在使用Game
  • game_id = models.AutoField(primary_key=True) p1 = models.ForeignKey(Player,related_name='player1',blank = True,null=True,on_delete=models.SET_NULL) p2 = models. ForeignKey(Player,related_name='player2',blank = True,null=True,on_delete=models.SET_NULL) board = models.ForeignKey(GameBoard,related_name='game_board',on_delete=models.CASCADE)

标签: python django django-models


【解决方案1】:

本例中的related_name 是Player 模型用来引用Game 模型对象的名称。在这种情况下令人困惑,因为 Player 模型可以由 Game.player_1 或 Game.player_2 字段引用。一个名为 player 的 ManyToMany 字段在这里可能更有意义。否则将related_name 的值更改为“game_1”和“game_2”或类似的值。

This question explains related_name well

Django documentation on related_name

【讨论】:

  • 好的,我发现即使尝试刷新数据库并重置迁移文件夹(可能不同步?),他的数据库也无法正常工作。我用相同的代码和建议创建了另一个应用程序,它以您建议的两种方式工作,谢谢!
猜你喜欢
  • 2012-04-28
  • 2019-07-27
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 1970-01-01
相关资源
最近更新 更多