Django的Form机制详解

环境:Python 2.7.5 + Django 1.6
使用Django,咱们能够以声明式的方式来定义一个Form,以下:
# -*- coding: utf-8 -*-
from django import forms
class SimpleForm(forms.Form):python

    field_a = forms.CharField(max_length=100)
    field_b = forms.CharField(max_length=100)
写起来很舒服,可是问题来了,当我把这个Form初始化以后,好比:shell

from polls.forms import SimpleForm
sf = SimpleForm({'field_a':'value of field_a', 'field_b':'value of field_b'})
而后在python shell里执行dir(sf),发现该实例并无field_a和field_b这两个属性,显然咱们就不能像sf.field_a这么来引用sf上的字段了。但是明明咱们能够在template里以{{ form_name.field_name }}的形式来引用form的字段,这是怎么回事呢?django

一番调查以后发现背后的实现机制还比较曲折。首先,若是咱们要引用form里的字段应该怎么写呢?应该这么写:sf['field_a']spa

Python教程 http://www.iplaypython.com/

为何要这么写呢?上代码,django.forms.BaseForm的__getitem__方法:orm

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)
#更多关于Django的内容,玩蛇网的Python培训课程中会讲解到。对象

这样就把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生成了一个新的类。ip

相关文章
相关标签/搜索