简体   繁体   中英

Django throws a Foreign Key IntegrityError with a valid ForeignKey

I am creating a project in Django for a multiplayer battleship game, I am trying to set up my database so I can record games, players and user actions, here is the app/model.py code

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)

Then I run makemigrations and migrate to update the database. Finally I try to test the code by using 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()

When I run this code I receive the following error: django.db.utils.IntegrityError: FOREIGN KEY constraint failed. I also tried to save a game with no players:

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

The previous code is able to execute without error, I also checked the saved object on the database and it actually saved it correctly.

I assume that the issue is with p1 and p2, however I don't understand why, since board is a foreign key as well. I am assuming this depends on the null=True in the Player model, however I don't see the problem with that parameter being there (if a player is deleted I want to update the existing game names to null instead of deleting on cascade).

The related_name in this case is what is used by the Player model to reference objects of the Game model. It is confusing in this case as the Player model can be referenced by either the Game.player_1 or Game.player_2 fields. A ManyToMany field called players may make more sense here. Otherwise change the value of related_name to "game_1" and "game_2" or similar.

This question explains related_name well

Django documentation on related_name

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM