我知道关于同一主题存在很多问题,但我对一点感到困惑。 我的目的是在表单上显示两个ModelChoiceFields,但不直接将它们绑定到Game模型。
我有以下内容:
forms.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')
Views.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 )
现在它运作正常。
所以我的问题是,两条线之间有什么区别?为什么第二个工作而不是第一个?我确信这是一个新手(我是一个)的问题,但我很困惑。
任何帮助都将不胜感激。
答案 0 :(得分: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']
,您将访问field that python can understand。这是因为如果from已经获得了任何输入,那么就会发生验证和数据转换(事实上,这些是用于此的字段,the general process of validation有点复杂)。
我希望这可能会为你解决一些问题,但正如你所看到的,整个form's API真的很复杂。对于最终用户来说非常简单,但幕后有很多编程:)
阅读链接提供将有助于消除您的疑虑,并将提高您对这个非常有用的主题和Django的了解。
祝你好运!更新:顺便说一下,如果您想了解有关该主题的Python的元类,this is a hell of an answer的更多信息。
答案 1 :(得分:0)
在你views.py
中,你有这一行:
form = AddGame(request.POST or None, instance=game)
所以form
是类AddGame
的Form对象(旁注:您应该将名称更改为AddGameForm
以避免混淆)。
由于home_team
是AddGame
类中的字段,因此它不是form
对象中的属性。这就是您无法通过form.home_team
访问它的原因。
但是,Django Form API为任何表单对象提供fields
属性,这是一个包含所有表单字段的dict。这就是您可以访问form.fields['home_team']
的原因。
最后,由于home_team
是ModelChoiceField
,因此它可以包含queryset
属性,这就是您可以访问form.fields['home_team'].queryset