使用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生成了一个新的类。

Django的Form机制小问题的更多相关文章

  1. 转载:Django之form表单

    转载: 一.使用form类创建一个表单 先定义好一个RegForm类: forms.py from django import forms # 导入forms类 class NameForm(form ...

  2. Django---form表单提交数据到数据库(普通方法+Django的form类)

    目标: ①.初始form的简单应用 ②.使用Django的form组件完成新增一个帖子 方法一:普通方法 1.前端表单代码 <div> <form class="navba ...

  3. Django之Form组件(一)

    Django之Form组件(一) Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 基本操作:字 ...

  4. python框架之Django(10)-Form组件

    介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来.与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入 ...

  5. Django之Form、ModelForm 组件

    Django之Form.ModelForm 组件 一.Form组件: django框架提供了一个form类,来处理web开发中的表单相关事项.众所周知,form最常做的是对用户输入的内容进行验证,为此 ...

  6. Django 09 博客小案例

    Django 09 博客小案例 urls.py from django.urls import path from . import views urlpatterns = [ path('index ...

  7. Django 之 Form 组件

    常用功能 From 组件主要有以下几大功能: 生成 HTML 标签 验证用户数据(显示错误信息) HTML Form 提交保留上次提交数据 初始化页面显示内容 小试牛刀 下面我们通过 Form 组件来 ...

  8. Django之Form、跨站请求以及cookie、session

    Form表单 常规html页面的form表单验证 常规页面中,如果想实现对表单中用户输入信息的数据验证,需要配合Ajax来实现. 使用前我们先来熟悉下函数参数:request,其中包含的意义: req ...

  9. Django之Form组件

    Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功能: 生成HTML标签 验证用户 ...

随机推荐

  1. URL访问 和命名规范

    手册:http://v9.help.phpcms.cn/html/2010/structure_0928/71.html http://yourdomain.com/index.php?m=conte ...

  2. python学习之argparse模块的使用

    以下内容主要来自:http://wiki.jikexueyuan.com/project/explore-python/Standard-Modules/argparse.html argparse ...

  3. MVVM设计模式的事件绑定

    为什么要事件绑定 这个问题其实是很好理解的,因为事件是丰富多样的,单纯的命令绑定远不能覆盖所有的事件.例如Button的命令绑定能够解决Click事件的需求,但Button的MouseEnter.窗体 ...

  4. 使用数据库管理工具打开MySql

    1.推荐使用软件:Navicat_Premium_11.0.10.exe.  下载地址:http://pan.baidu.com/s/1nu6mTF7 2.下载上面文件并安装. 3.打开Navicat ...

  5. 项目中遇到的问题:Gradle传递性依赖冲突

    问题描述: 在调用别人接口时,由于他们接口做了拦截处理在使用RestTemplate调用时必须要使用@Qualifier("他们封装好的类"),需要导入jar包 gradle方式导 ...

  6. invalid byte sequence for encoding "UTF8": 0xe99d2c

    服务器还原数据库数据出错,老规矩... 字符集编码的问题 http://blog.csdn.net/beiigang/article/details/39582583 over....

  7. Linux入门(二)Shell基本命令

    上一篇讲了普通用户切换到root用户,今天补充一点,对于Debian和Ubuntu用户,安装时候只有一个普通用户注册,在需要root权限时,我们可以在普通用户模式下输入sudo这个命令运行某些相关特权 ...

  8. Java - 利用StringEscapeUtils对字符串进行各种转义与反转义

    来自:http://blog.csdn.net/chenleixing/article/details/43456987 --------------------------------------- ...

  9. 使用django发送邮件时的连接超时问题解决

    一.报错 研究报错半天,没看出代码有什么毛病,就是发送邮件时连接超时,发送邮件的连接用户名密码都没有错误,于是就网上各种查... 终于皇天不负有心人,找到答案了.. 在服务器上输入telnet smt ...

  10. servlet 学习笔记(二)

    ---------------------第二讲--------------------------------- 开发servlet有三种方法: 1.实现servlet接口(最原始的) 实现接口的5 ...