使用Django,我们可以以声明式的方式来定义一个Form,如下:

1
2
3
4
5
# -*- 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'})

然后在python shell里执行dir(sf),发现该实例并没有field_a和field_b这两个属性,显然我们就不能像sf.field_a这么来引用sf上的字段了。可是明明我们可以在template里以{{ form_name.field_name }}的形式来引用form的字段,这是怎么回事呢?

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

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

1
2
3
4
5
6
7
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生成了一个新的类。

最新文章

  1. python_java_selenium_ jenkins持续集成Firfox_chrome浏览器不显示的解决方法?
  2. mysql安装及配置服务
  3. Python操作RabbitMQ
  4. MT5:放大市场价格指标
  5. oracle中Update方法
  6. 给iOS开发新手送点福利,简述文本属性Attributes的用法
  7. 解决matplotlib的中文问题
  8. CSS浮动属性Float介绍
  9. oracle 行列转换的运用
  10. Android的四大组件
  11. 怎样加快master数据库的写操作?分表原则!将表水平划分!或者添加写数据库的集群
  12. shell复习笔记----命令与参数
  13. 在线CSS圆角生成器
  14. select语句返回结果的顺序问题 .
  15. Matrix(多线程dp)
  16. HDU 2080 夹角有多大II (数学) atan(y/x)分类求角度
  17. [转帖]流程控制:for 循环
  18. django中 自定义User报错 已经注册的错误
  19. set_include_path和get_include_path用法详解
  20. 7.24-Codeforces Round #494 (Div. 3)

热门文章

  1. DNS域传送漏洞
  2. 创造101:如果软件测试工程师组团出道,怎样才能站C位?!
  3. 【多视图几何】TUM 课程 第4章 同名点匹配
  4. go 函数举例练习
  5. Nodejs 发送邮件
  6. plupload 上传组件的使用
  7. 你的组织使用了 windows defender 应用程序控制来阻止此应用
  8. 字符串匹配算法之 kmp算法 (python版)
  9. MySQL通过rpm安装及其单机多实例部署
  10. python 比timedelta强大的多的 relativedelta