1

我知道关于同一主题存在许多问题,但我在某一点上感到困惑。我的意图是在表单上显示两个 ModelChoiceField,但不直接将它们绑定到 Game 模型。

我有以下内容:

表格.py

class AddGame(forms.ModelForm):
    won_lag = forms.ChoiceField(choices=[('1','Home') , ('2', 'Away') ])
    home_team = forms.ModelChoiceField(queryset=Player.objects.all())
    away_team = forms.ModelChoiceField(queryset=Player.objects.all())

    class Meta:
        model = Game
        fields = ('match', 'match_sequence')

视图.py

def game_add(request, match_id):
    game = Game()
    try:
        match = Match.objects.get(id=match_id)
    except Match.DoesNotExist:
        # we have no object!  do something
        pass

    game.match = match

    # get form
    form = AddGame(request.POST or None, instance=game)
    form.fields['home_team'].queryset = Player.objects.filter(team=match.home_team )

    # handle post-back (new or existing; on success nav to game list)
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            # redirect to list of games for the specified match
            return HttpResponseRedirect(reverse('nine.views.list_games'))

    ...

我感到困惑的是在设置查询集过滤器时。首先我试过:

form.home_team.queryset = Player.objects.filter(team=match.home_team )

但我收到了这个错误

AttributeError at /nine/games/new/1 
'AddGame' object has no attribute 'home_team'
...

所以我将其更改为以下内容:(阅读其他帖子后)

form.fields['home_team'].queryset = Player.objects.filter(team=match.home_team )

现在它工作正常。

所以我的问题是,这两条线有什么区别?为什么第二个有效而不是第一个?我确信这是一个新手(我是一个)问题,但我很困惑。

任何帮助,将不胜感激。

4

2 回答 2

3

Django 表单是metaclasses

>>> type(AddGame)
<class 'django.forms.forms.DeclarativeFieldsMetaclass'>

他们基本上根据其定义中给出的信息创建一个表单实例。AddGame这意味着,当您定义表单时,您不会得到您所看到的确切内容。当您实例化它时,metaclass将返回带有提供的字段的正确实例:

>>> type(AddGame())
<class 'your_app.forms.AddGame'>

因此,使用实例,您可以通过简单地访问字段form.field。事实上,它比这更复杂一些。您可以访问两种类型的字段。form['field']您将访问一个BoundField. 用于输出和 raw_input。

通过这样做form.fields['fields'],您将可以访问python 可以理解的字段。这是因为如果 from 已经有任何输入,就会在其中进行验证和数据转换(实际上,这些是用于此的字段,验证的一般过程有点复杂)。

我希望这可能会为您解决一点问题,但正如您所见,整个表单的 API确实很大而且很复杂。对于最终用户来说非常简单,但它在幕后有很多编程:)

阅读提供的链接将有助于消除您的疑虑,并将提高您对这个非常有用的主题和一般 Django 的知识。

祝你好运!

更新:顺便说一句,如果你想了解更多关于 Python 元类的信息,这是一个关于这个主题的地狱般的答案。

于 2013-07-31T22:54:21.827 回答
0

在 youviews.py中,您有这一行:

form = AddGame(request.POST or None, instance=game)

form类的 Form 对象也是如此AddGame(旁注:您应该更改名称AddGameForm以避免混淆)。

由于home_teamAddGame类中的字段,因此它不是form对象中的属性。这就是为什么您无法通过form.home_team.

但是,Django Form API 为fields任何表单对象提供属性,这是一个包含所有表单字段的字典。这就是为什么您可以访问form.fields['home_team'].

最后因为home_teamis a ModelChoiceField,它可以包含一个queryset属性,这就是你可以访问的原因form.fields['home_team'].queryset

于 2013-07-31T22:30:30.563 回答