Django的Form機制詳解

高洛峰
發布: 2016-10-17 14:04:28
原創
1120 人瀏覽過

環境: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 polls.forms import SimpleForm

sf = SimpleForm({'field_a':'value of field_a', 'field_b':'value of field_b'})

(sf),發現該實例並沒有field_a和field_b這兩個屬性,顯然我們就不能像sf.field_a這麼來引用sf上的字段了。可是明明我們可以在template裡以{{ form_name.field_name }}的形式來引用form的字段,這是怎麼回事呢?

    一番調查之後發現背後的實現機制還比較曲折。首先,如果我們要引用form裡的欄位該怎麼寫呢?應該要這樣寫: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裡的字段。

    新的問題又來了,為什麼可以在template裡以{{ form_name.field_name }}的形式來引用form的欄位呢?請參閱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的值賦給了將要產生的類別的base_fields屬性,然後基於SimpleForm產生了一個新的類別。


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板