像Manytomanyfield中的Foreignkey中的Foreignkey中是否有贯穿模型?

时间:2019-07-10 02:38:23

标签: python-3.x django-models

我正在开始类似网络的电子竞技。我有一堂课叫做比赛和锦标赛。 锦标赛具有外键和游戏。游戏中有对象pubg和clashroyale。使用比赛发布创建锦标赛时,它必须具有一个称为“ prize_per_kill”的属性。但不适用于其他游戏。当使用该游戏创建时,它对于该锦标赛必须是唯一的。我该怎么办?

我曾考虑过使用多方场地,但一场比赛只有一场比赛。因此它必须是外键。 我希望可以在详细页面中反复浏览该锦标赛的特殊属性。

'''

class Tournament(models.Model):
    game = models.ForeignKey(Game, on_delete=models.CASCADE)
    players = models.ManyToManyField(User,through="Subscription")
    max_players = models.IntegerField(default=100)
    tourney_type = models.CharField(max_length=20)
    price = models.IntegerField()
    time = models.DateTimeField()
    tourney_id = models.CharField(max_length=50)
    tourney_pass = models.CharField(max_length=15)
    first_prize = models.IntegerField()
    second_prize = models.IntegerField()
    third_prize = models.IntegerField()

'''

'''

class Game(models.Model):
    users = models.ManyToManyField(User, through="Membership")
    name = models.CharField(max_length=20)
    desc = models.TextField()

'''

1 个答案:

答案 0 :(得分:0)

您可以创建一个抽象Game模型,PubgGameClashRoyaleGame模型,这些模型从您的抽象模型继承。这将给您两个主要的灵活性:

  1. 由于Game将是一个抽象模型,因此不会为其创建任何表。您只会有PubgGame等游戏模型的表格。
  2. 您可以为每个游戏添加特定字段,例如prize_per_kill

但是使用这种解决方案会出现问题;您的抽象模型不能在其他模型中用作ForeignKey。因此,您需要找到一种在一个ForeignKey字段中表示PubgGameClashRoyaleGame模型的方法。 Django为此有一个特殊字段:GenericForeignKey。您需要指向GenericForeignKey的CoontentType和PositiveIntegerField才能存储游戏模型的主键ID。

# models.py
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models

class Game(models.Model):
    users = models.ManyToManyField(User, through="Membership")
    name = models.CharField(max_length=20)
    desc = models.TextField()

    class Meta:
        abstract = True

class PubgGame(Game):
    prize_per_kill = models.TextField() # I dont know what prize_per_kill means :)

class ClashRoyaleGame(Game):
    some_other_field = models.TextField()

class Tournament(models.Model):
    players = models.ManyToManyField(User,through="Subscription")
    max_players = models.IntegerField(default=100)
    tourney_type = models.CharField(max_length=20)
    price = models.IntegerField()
    time = models.DateTimeField()
    tourney_id = models.CharField(max_length=50)
    tourney_pass = models.CharField(max_length=15)
    first_prize = models.IntegerField()
    second_prize = models.IntegerField()
    third_prize = models.IntegerField()

    # GenericForeignKey related fields
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    game = GenericForeignKey('content_type', 'object_id')

然后您可以使用以下字段:

>>> from your_ap.models import Tournament, PubgGame
>>> pubg_game = PubgGame.objects.create(prize_per_kill="some value")
>>> tournament = Tournament.objects.create(game=pubg_game) # I'm not setting other fields for simplicity.
>>> tournament.save()
>>> tournament.game_object # This will give you a PubgGame model object