1

我正在建立一个用户可以购买球员的平台(比如幻想联赛)。所以我有4个模型:

POSITION_CHOICES = ((1,'1'),
                    (2,'2'),
                    (3,'3'),
                    (4,'4'),
                    (5,'5'),
)

class Team(models.Model):
    ...

class Player(models.Model):
    team = models.ForeignKey(Team, blank=True, null=True, ...)
    position = MultiSelectField(
    user = models.ForeignKey(User, unique=True)
    player1 = models.ForeignKey(Player, related_name='+', blank=True,null=True,
                                limit_choices_to={'position__icontains':1},...)
    player2 = ...
    player3 = ...
    player4 = ...
    player5 = ...
    ...

class FantasyTeams(models.Model):
    user = models.ForeignKey(User, unique=True)
    team1 = models.ForeignKey(Team, verbose_name='Team', blank=True, null=True,
                              on_delete=models.SET_NULL)
    ...

基本上 aTeam包含 0 或更多PlayersFantasyPlayers和都是FantasyTeams用户购买的球员和球队(他可以购买 0 到 5 名球员和 0 到 1 支球队,但这些数字可能会改变)。LUTION 我目前的做法很丑,即使它有效。我现在正在寻找更简洁的东西(因为我觉得这根本不是通用的),比如替换包含列表的player#字段。我也愿意将 2 个模型和合并为一个,其中包含一个球员列表(最多 5 个)、一个团队列表(最多 1 个)和它的用户。playersForeignKeyFantasyPlayersFantasyTeamsForeignKey

在查看类似问题时,我看到多次提到一对多字段,但它所做的只是让我更加困惑于OneToOneFieldManyToManyField.

你有什么方向可以让我ForeignKey在 Django 模型中存储一个列表吗?


解决方案

以下是替换以前的FantasyPlayersand FantasyTeams

class FantasyTeam(models.Model):
    user = models.ForeignKey(User, unique=True)
    players = models.ManyToManyField(Player, blank=True, null=True)
    teams = models.ManyToManyField(Team, blank=True, null=True)
    ...

这就是我现在创建和保存模型的方式(通过ModelForm):

def fantasy_create(request):
    # Handling form datas
    if request.method == "POST":
        form = EditFantasyTeamForm(request.POST)
        if form.is_valid():
            fantasy = FantasyTeam.objects.create(user=request.user)
            for player in form.cleaned_data['players']:
                fantasy.players.add(player)
            for team in form.cleaned_data['teams']:
                fantasy.teams.add(team)
            return redirect(...)
    # Form is not submitted yet
    else:
        form = EditFantasyTeamForm()

    return render_to_response(...)


def fantasy_edit(request):
    # Fetching the FantasyTeam object
    fantasy = ...
    # Handling form datas
    if request.method == "POST":
        form = EditFantasyTeamForm(request.POST, instance=fantasy)
        if form.isLUTION_valid():
            form.save()
        return redirect(...)
    # Form not submitted yet
    else:
        form = EditFantasyTeamForm(instance=fantasy)

    return render_to_response(...)choices=POSITION_CHOICES, max_length=10)
    ...

class FantasyPlayers(models.Model):
    user = models.ForeignKey(User, unique=True)
    player1 = models.ForeignKey(Player, related_name='+', blank=True,null=True,
                                limit_choices_to={'position__icontains':1},...)
    player2 = ...
    player3 = ...
    player4 = ...
    player5 = ...
    ...

class FantasyTeams(models.Model):
    user = models.ForeignKey(User, unique=True)
    team1 = models.ForeignKey(Team, verbose_name='Team', blank=True, null=True,
                              on_delete=models.SET_NULL)
    ...

基本上 aTeam包含 0 或更多PlayersFantasyPlayers和都是FantasyTeams用户购买的球员和球队(他可以购买 0 到 5 名球员和 0 到 1 支球队,但这些数字可能会改变)。LUTION 我目前的做法很丑,即使它有效。我现在正在寻找更简洁的东西(因为我觉得这根本不是通用的),比如替换包含列表的player#字段。我也愿意将 2 个模型和合并为一个,其中包含一个球员列表(最多 5 个)、一个团队列表(最多 1 个)和它的用户。playersForeignKeyFantasyPlayersFantasyTeamsForeignKey

在查看类似问题时,我看到多次提到一对多字段,但它所做的只是让我更加困惑于OneToOneFieldManyToManyField.

你有什么方向可以让我ForeignKey在 Django 模型中存储一个列表吗?


解决方案

以下是替换以前的FantasyPlayersand FantasyTeams

class FantasyTeam(models.Model):
    user = models.ForeignKey(User, unique=True)
    players = models.ManyToManyField(Player, blank=True, null=True)
    teams = models.ManyToManyField(Team, blank=True, null=True)
    ...

这就是我现在创建和保存模型的方式(通过ModelForm):

def fantasy_create(request):
    # Handling form datas
    if request.method == "POST":
        form = EditFantasyTeamForm(request.POST)
        if form.is_valid():
            fantasy = FantasyTeam.objects.create(user=request.user)
            for player in form.cleaned_data['players']:
                fantasy.players.add(player)
            for team in form.cleaned_data['teams']:
                fantasy.teams.add(team)
            return redirect(...)
    # Form is not submitted yet
    else:
        form = EditFantasyTeamForm()

    return render_to_response(...)


def fantasy_edit(request):
    # Fetching the FantasyTeam object
    fantasy = ...
    # Handling form datas
    if request.method == "POST":
        form = EditFantasyTeamForm(request.POST, instance=fantasy)
        if form.isLUTION_valid():
            form.save()
        return redirect(...)
    # Form not submitted yet
    else:
        form = EditFantasyTeamForm(instance=fantasy)

    return render_to_response(...)
4

2 回答 2

2

你应该使用一个ManyToManyField

players = models.ManyToManyField(Player, ...)

但是只有当一个Player实例可以属于多个FantasyPlayers实例时才可以(同样的事情Team)如果一个Player实例只能属于一个FantasyPlayers实例,您应该反转关系并将一个ForeignKey字段FantasyPlayers放入Player模型中,然后您可以使用related_field访问列表Player来自一个实例的FantasyPlayers实例。

于 2013-04-16T17:27:34.540 回答
1

这个解决方案怎么样?(我不确定ManyToManyField是不是最好的选择。)

class FantasyPlayer(models.Model):
    user = models.ForeignKey(User, unique=True)
    player = models.ForeignKey(Player)
    position = models.MultiSelectField(choices=POSITION_CHOICES, max_length=10)

# To get a list of players
user_fantasy_players = user.fantasyplayer_set.all()

它的一个缺点是无法在编辑时limit_choices_to仅允许选择Player匹配位置FantasyPlayer(如您的示例所示),但这可以通过另一种方式解决。从长远来看,拥有更优雅和健全的数据架构更为重要,IMO。

于 2013-04-16T19:41:14.590 回答