1

この同じトピックについて多くの質問があることは知っていますが、1 つの点で混乱しています。私の意図は、フォームに 2 つの ModelChoiceFields を表示することですが、それらを 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')

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 )

今では正常に動作します。

私の質問は、2 つの行の違いは何ですか? 最初のものではなく、2番目のものはなぜ機能したのですか? 私はそれが初心者(私は1人です)の質問だと確信していますが、私は困惑しています。

どんな助けでも大歓迎です。

4

2 に答える 2

3

Django フォームは次のmetaclassesとおりです。

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

基本的に、定義で指定された情報に従ってフォーム インスタンスを作成します。AddGameつまり、フォームを定義したときに表示されるものを正確に取得することはできません。インスタンス化すると、metaclass提供されたフィールドを持つ適切なインスタンスが返されます。

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

したがって、インスタンスを使用すると、 を実行するだけでフィールドにアクセスできますform.field。実際には、それよりも少し複雑です。アクセスできるフィールドには 2 種類あります。にform['field']アクセスしBoundFieldます。出力と raw_input に使用されます。

そうすることで、python が理解できるフィールドform.fields['fields']にアクセスすることになります。これは、 from がすでに入力を取得している場合、検証とデータ変換が行われる場所があるためです (実際、これらはこのために使用されるフィールドであり、検証の一般的なプロセスはもう少し複雑です)。

これで問題が少し解決することを願っていますが、ご覧のとおり、フォーム全体の APIは非常に大きく複雑です。エンドユーザーにとっては非常にシンプルですが、カーテンの後ろに多くのプログラミングがあります:)

提供されているリンクを読むと、疑問が解消され、この非常に有用なトピックと Django 全般に関する知識が向上します。

幸運を!

更新:ところで、Python のメタクラスについて詳しく知りたい場合、これはこのトピックに関する非常に難しい回答です。

于 2013-07-31T22:54:21.827 に答える
0

youviews.pyには、次の行があります。

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

クラスのFormformオブジェクトも同様ですAddGame(補足:AddGameForm混乱を避けるために、名前を に変更する必要があります)。

はクラスhome_teamのフィールドであるため、オブジェクトの属性ではありません。そのため、経由でアクセスすることはできません。AddGameformform.home_team

ただし、Django フォーム API はfields、すべてのフォーム フィールドを含む dict である任意のフォーム オブジェクトに属性を提供します。というわけでアクセスできますform.fields['home_team']

そして最後にhome_teamは であるため、属性ModelChoiceFieldを含めることができるため、アクセスできますquerysetform.fields['home_team'].queryset

于 2013-07-31T22:30:30.563 に答える