Nicholas
Nicholas

Reputation: 13

How to fix "more than one foreign key" Django

I am new to Django (using version: 2.1.5)(Python 3.6) and trying to mess around with some models. I am building a chess database. This relies on 3 models, the players, the game and the moves comprising the game. For each game there is a white player and a black player, both of the class player. This raises an error:

<'class 'chessengine.admin.GameInline'>: (admin.E202) 'chessengine.Game' has more than one ForeignKey to 'chessengine.Player'.

I tried using reference names which removed an earlier related error but will not deal with the one above.


//models.py


class Player(models.Model):

    name = models.CharField(max_length=200)
    birth_date = models.DateField('birthday')

    def game_count(self):
        return Player.objects.filter(Games__white_player=self.name).count() + Player.objects.filter(Games__black_player=self.name).count()


class Game(models.Model):

    number = models.IntegerField()
    date = models.DateField('date played')
    moves = models.IntegerField()
    white_player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='white_player')
    black_player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='black_player')
    result = models.CharField(max_length=8)

//admin.py

class GameInline(admin.TabularInline):

    inlines = [MoveInline]
    model = Game


class PlayerAdmin(admin.ModelAdmin):

    fieldsets = [
        ('Player Information',               {'fields': ['name', 'birth_date']}),
        ('Game Information', {'fields': ['date', 'player_white', 'player_black', 'result'], 'classes': ['collapse']}),
    ]
    inlines = [GameInline]
    list_display = ('name', 'birth_date', 'game_count')
    list_filter = ['name']

Upvotes: 0

Views: 1540

Answers (2)

Arpit Svt
Arpit Svt

Reputation: 1203

Since Game model has multiple ForeignKey to Player model. So while defining TabularInline for Game ie. GameInline you have to add fk_name to GameInline

class GameInline(admin.TabularInline):
    inlines = [MoveInline]
    model = Game
    fk_name = 'white_player`

Read more about fk_name here

Upvotes: 2

chrymxbrwn
chrymxbrwn

Reputation: 98

You can't have two references to the Player Table in that fashion. What you should to is have a type for player (and make use of the choice fields possibly) that will be either white or black:

class Player(models.Model):

    PLAYER_TYPES = (("W", "White"), ("B", "Black")

    type = models.CharField(max_length=5, blank=False, null=False, choices=PLAYER_TYPES)
    name = models.CharField(max_length=200)
    birth_date = models.DateField('birthday')

def game_count(self):
    return Player.objects.filter(Games__white_player=self.name).count() + Player.objects.filter(Games__black_player=self.name).count()


class Game(models.Model):

    number = models.IntegerField()
    date = models.DateField('date played')
    moves = models.IntegerField()
    player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='player')
    result = models.CharField(max_length=8)

EDIT: It appears you can have two references to the player table, but I would likely still implement a choice or similar solution..

Upvotes: 0

Related Questions