ホームページ > バックエンド開発 > Python チュートリアル > DjangoのFormの仕組みを詳しく解説

DjangoのFormの仕組みを詳しく解説

高洛峰
リリース: 2016-10-17 14:04:28
オリジナル
1154 人が閲覧しました

環境: 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 に基づく新しいクラス。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート