将 ForeignKeyed 对象中的字段值用于 ModelChoiceFields

Using field values from a ForeignKeyed object for ModelChoiceFields

我和我的朋友们玩了一个基于电子表格的运动选择游戏,更改起来非常繁琐。我想学习 Django 有一段时间了,所以我一直致力于将它创建为一个 webapp。以下是我正在使用的模型:

class Sheet(models.Model):
user = models.ForeignKey(User)
... other stuff

class Game(models.Model):
home_team = models.CharField(max_length=100, default='---')
away_team = models.CharField(max_length=100, default='---')
... other stuff

class Pick(models.Model):
sheet = models.ForeignKey(Sheet)
game = models.ForeignKey(Game)
HOME = 'H'
AWAY = 'A'
PICK_TEAM_CHOICES = (
    (HOME, 'Home'),
    (AWAY, 'Away'),
)
pick_team = models.CharField(max_length=4,
                                  choices=PICK_TEAM_CHOICES,
                                  default=HOME)
... other stuff

现在,我正在尝试确定一种简单的方法来显示以下表单,其中包含来自外键模型的信息,而不是 pick_team 默认选项。 game 是隐藏的,因为它通过使用视图中的 initial 功能与生成的 PickForm 配对。

class PickForm(ModelForm):
  class Meta:
      model = Pick
      widgets = {'game': forms.HiddenInput()}
      fields = ['sheet','game','amount','pick_type','pick_team']

  def __init__(self, *args, **kwargs):
      game = kwargs['initial']['game']
      super(PickForm, self).__init__(*args, **kwargs)
      self.fields['pick_team']=forms.ModelChoiceField([game.away_team,game.home_team])

据我所知,ModelChoiceField 需要一个查询集 - 因此当我提供列表或元组时,我收到 'list' object has no attribute 'iterator' 错误。现在知道了这一点,如何在模板的 pick_team 下拉列表中显示游戏字段 home_teamaway_team?目前它默认为 'Home' 和 'Away'.

我知道这是一个核心的常见问题 - 如何在下拉列表中显示外键信息,但是我找到的所有答案都可以向 ModelChoiceField 提供查询集,因为它们通常试图列出来自每个对象(或某些过滤子集)的字段。在这种情况下,我只想列出 2 个字段,并且只来自一个对象。

我尝试返回一个由 kwargs 中已经存在的 Game 对象组成的查询集,但它只在下拉列表中显示游戏的 str() 方法,并试图优化查询集使用相关字段名称也不起作用。

编辑:我意识到实际上使用 Game 对象中的 home_teamaway_team 值在保存 Pick 时需要额外的处理,或者可能更难比起那个来说。有什么办法可以单独在模板中进行这种别名处理吗?与选择字段的方式类似,我可以使用 get_pick_team_display 来显示更好看的显示值('Home'、'Away'),而不是模糊的 'H' 或 'A'。

EDIT2:查看代码 class 游戏细节(细节视图): #model = 游戏 template_name = 'app/games.html' context_object_name = 'game_detail'

def get_object(self):
    game = get_object_or_404(...object filtering)
    return game

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    try:
        pick = Pick.objects.get(game=context['game_detail'],
     ....other stuff)

        context['pickform'] = PickForm(initial={'game':context['game_detail'],
     .... other stuff
    except Pick.DoesNotExist:
        #pick = none
        context['pickform'] = PickForm(initial={'game':context['game_detail'],
                                            })

    return context

def post(self, request, *args, **kwargs):
    form = PickForm(request.POST)
    if form.is_valid():
        ....process form

这是一种快速修复方法。在您的 __init__ 中,不要重新分配 pick_team 字段,只需重新定义其选项如下:

self.fields['pick_team'].choices = (
    ('H', game.home_team),
    ('A', game.away_team),
)