環境: Python 2.7.5 + Django 1.6
Django を使用すると、次のように宣言的な方法で Form を定義できます:
# -*- coding: utf-8 -*- from django import forms class SimpleForm(forms.Form): field_a = forms.CharField(max_length=100) field_b = forms.CharField(max_length=100)
書くのは非常に快適ですが、問題はこの Form を初期化するときに発生します。たとえば、次のようになります:
from votes.forms import SimpleForm
sf = SimpleForm({'field_a':'value of field_a', 'field_b':'value of field_b'})
次に、Python シェルで dir を実行します。 (sf) では、このインスタンスには 2 つの属性 field_a と field_b がないことがわかります。明らかに、sf.field_a のような sf 上のフィールドを参照することはできません。しかし、明らかに、テンプレート内のフォーム フィールドは {{ form_name.field_name }} の形式で参照できます。
いくつか調査した結果、その背後にある実装メカニズムが非常に複雑であることがわかりました。まず、フォーム内のフィールドを参照したい場合はどのように書けばよいのでしょうか?このように書く必要があります: sf['field_a']
なぜこのように書く必要があるのでしょうか?上記のコード、django.forms.BaseForm の __getitem__ メソッド:
def __getitem__(self, name): "Returns a BoundField with the given name." try: field = self.fields[name] except KeyError: raise KeyError('Key %r not found in Form' % name) return BoundField(self, field, name)
これにより、BaseForm が dict のようなコンテナに変わり、上記の構文を使用してフォーム内のフィールドを参照できるようになります。
新しい質問がまた出てきました。なぜテンプレート内でフォーム フィールドを {{ form_name.field_name }} の形式で参照できるのでしょうか? Django の公式ドキュメントを参照してください: https://docs.djangoproject.com/en/1.6/topics/templates/#variables。 Django のテンプレート エンジンは、{{ form_name.field_name }} のような式に遭遇すると、form_name オブジェクトの辞書検索を実行するため、テンプレート エンジンが {{ sf.field_a }} を評価するときに、実際には sf を実行することがわかりました。 ['field_a ']、真実が明らかになりました。
さらに、上記の SimpleForm の型は実際には django.forms.DeclarativeFieldsMetaclass です。このメタクラスは、実際には、SimpleForm の宣言構文で宣言されたすべてのフィールド (親クラスの宣言フィールドを含む) を get_declared_fields メソッドを通じて dict に変換し、生成されるクラスに dict の値を代入して生成します。 SimpleForm に基づく新しいクラス。