Django 表单:处理用户提交的表单数据
HTML 表单是网站交互的经典方式。本章介绍如何使用Django处理用户提交的表单数据。
HTTP 请求
HTTP 协议以“请求-响应”方式工作。当客户发送请求时,他们可以向请求添加数据。服务器通过解析请求,可以获得客户端发送的数据,并根据URL提供特定的服务。
GET方法
我们在上一个项目中创建了一个search.py文件,用于接收用户请求:
# -*- coding: utf-8 -*- from django.http import HttpResponse from django.shortcuts import render_to_response # 表单 def search_form(request): return render_to_response('search_form.html') # 接收请求数据 def search(request): request.encoding='utf-8' if 'q' in request.GET: message = '你搜索的内容为: ' + request.GET['q'].encode('utf-8') else: message = '你提交了空表单' return HttpResponse(message)
将search_form.html表单添加到template文件夹template中:
<html> <head> <meta charset="utf-8" /> <title>Search - w3cschool.cc</title> </head> <body> <form action="/search/" method="get"> <input type="text" name="q"> <input type="submit" value="Search"> </form> </body> </html>
urls.py行更改它有如下形式:
from django.conf.urls import * from HelloWorld.view import hello from HelloWorld.testdb import testdb from HelloWorld import search urlpatterns = patterns("", ('^hello/$', hello), ('^testdb/$', testdb), (r'^search-form/$', search.search_form), (r'^search/$', search.search), )
访问地址:http://192.168.45.3:8000/search-form/并搜索,结果如下:
POST方法
我们使用了上面的GET方法。显示渲染和请求处理分为两个功能。
提交数据时更常用POST方法。我们在下面使用这个方法,并使用 URL 和处理函数来显示视图并同时处理请求。
我们在tmplate中创建post.html:
<html> <head> <meta charset="utf-8" /> <title>Search - w3cschool.cc</title> </head> <body> <form action="/search-post/" method="post"> {% csrf_token %} <input type="text" name="q"> <input type="submit" value="Submit"> </form> <p>{{ rlt }}</p> </body> </html>
在模板的末尾我们添加一个rlt标记来为表格处理结果保留一个位置。
表单后面还有一个标签{% csrf_token %}。 csrf的全称是跨站请求伪造。这是Django的一个功能,用于防止伪装的提交请求。通过 POST 方法发送的表单必须具有此标记。
在HelloWorld目录下新建search2.py文件,使用search_post函数处理POST请求:
# -*- coding: utf-8 -*- from django.shortcuts import render from django.core.context_processors import csrf # 接收POST请求数据 def search_post(request): ctx ={} ctx.update(csrf(request)) if request.POST: ctx['rlt'] = request.POST['q'] return render(request, "post.html", ctx)
urls.py 规则更改如下:
from django.conf.urls import * from HelloWorld.view import hello from HelloWorld.testdb import testdb from HelloWorld import search from HelloWorld import search2 urlpatterns = patterns("", ('^hello/$', hello), ('^testdb/$', testdb), (r'^search-form/$', search.search_form), (r'^search/$', search.search), (r'^search-post/$', search2.search_post), )
转到http://192.168.45.3 : 8000/search-post / 显示结果如下:
完成上面的例子后,我们的目录结构是:
HelloWorld |-- HelloWorld | |-- __init__.py | |-- __init__.pyc | |-- models.pyc | |-- search.py | |-- search.pyc | |-- search2.py | |-- search2.pyc | |-- settings.py | |-- settings.pyc | |-- testdb.py | |-- testdb.pyc | |-- urls.py | |-- urls.pyc | |-- view.py | |-- view.pyc | |-- wsgi.py | `-- wsgi.pyc |-- TestModel | |-- __init__.py | |-- __init__.pyc | |-- admin.py | |-- models.py | |-- models.pyc | |-- tests.py | `-- views.py |-- manage.py `-- templates |-- base.html |-- hello.html |-- post.html `-- search_form.html 3 directories, 29 files
Request对象
每个显示函数的第一个参数是一个HttpRequest对象,就像以下 hello() 函数:
from django.http import HttpResponse def hello(request): return HttpResponse("Hello world")
HttpRequest 对象包含有关当前请求的 URL 的一些信息:
属性 | 描述 |
路径 | 请求页面的完整路径,不包括域名 -例如“/你好/”。 |
method | 请求中使用的 HTTP 方法的字符串表示形式。用大写字母表示。例如: if request.method == 'GET': |
GET | 包含所有HTTP 类似字典的 GET 参数对象。请参阅 QueryDict 文档。 |
POST | 一个类似字典的对象,包含所有 HTTP POST 参数。请参阅 QueryDict 文档。 服务器也有可能收到一个空的POST请求。换句话说,表单通过 HTTP POST 方法发送请求,但表单中没有数据。因此,不能使用if request.POST语句来判断是否使用HTTP POST方法;请改用 if request.method == "POST" (请参阅此表中的方法属性)。 注意:POST 不包含文件上传信息。请参阅 FILES 属性。 |
REQUEST | 为了方便起见,该属性是POST和GET属性的集合,但它有特殊的功能。首先查找 POST 属性,然后查找 GET 属性。学习PHP的$_REQUEST。 如果 GET = {"name": "john"} 且 POST = {"age": '34'},则 REQUEST["name"] 的值为 "john",REQUEST["age "] 的值为“34”。 强烈建议使用 GET 和 POST,因为这两个属性更明确,写出的代码也更容易理解。 |
COOKIES | 包含所有 cookie 的标准 Python 字典对象。键和值都是字符串。有关 cookie 的更详细说明,请参阅第 12 章。 |
FILES | 一个类似字典的对象,包含所有上传的文件。FILES 中的每个键都是 标记中 name 属性的值。 FILES 中的每个值也是一个标准的 Python 字典对象,包括以下三个键:
注意:只有当请求方式为POST且请求页面FILES包含数据时,只有具有enctype="multipart/form-data"属性。否则,FILES 是一个空字典。 |
META | 包含所有可用 HTTP 标头信息的字典。例如:
META 这些 header 以 HTTP_ 为前缀作为 key,例如:
|
raw_post_data | 原始 HTTP POST 数据,未解析。对于高级加工很有用。 |
Request 对象还有一些有用的方法:
方法 | 描述 |
---|---|
__getitem__(key) | 返回 GET/POST 的键值,先取 POST,再取 GET。如果密钥不存在,则抛出 KeyError。 这是我们使用字典语法访问 HttpRequest 对象的地方。例如, Request["foo"] 等于 request.POST["foo"] 然后是 request.GET["foo"]。 |
has_key() | 检查 request.GET 或 request.POST 是否包含参数指定的 key。 |
get_full_path() | 返回包含查询字符串的请求路径。例如:“/music/bands/the_beatles/?print=true” |
is_secure() | 如果请求是安全的,即发送了 HTTPS 请求,则返回 True。 |
QueryDict 对象
在 HttpRequest 对象中,GET 和 POST 属性是 django.http.QueryDict 类的实例。
QueryDict 是一个类似字典的自定义类,用于处理单个键匹配多个值的情况。
QueryDict 实现了所有标准字典方法。它还包含一些独特的方法:
方法 | 描述 | |
---|---|---|
__getitem__ | 与标准字典处理略有不同,即如果 Key 匹配多个值,__getitem__() 返回最后一个值。 | |
__setitem__ | 设置参数指定的键的值列表(Python 列表)。注意:它只能在可变的 QueryDict 对象(即由 copy() 生成的 QueryDict 对象的副本)上调用。 | |
get() | 如果键匹配多个值,get() 返回最后一个值。 | |
update() | 参数可以是QueryDict或标准字典。与标准字典更新方法不同,此方法添加字典项目而不是替换它们: >>> q = QueryDict('a=1') >>> q = q.copy() # to make it mutable >>> q.update({'a': '2'}) >>> q.getlist('a') ['1', '2'] >>> q['a'] # returns the last ['2'] | |
items() | 它与标准字典的 items() 方法略有不同。该方法使用单值逻辑 __getitem__( ; 方法 | 描述 |
copy() | 返回对象的副本。内部实现是来自 Python 标准库的 copy.deepcopy()。副本为mutable:即副本的值是可以改变的。 | |
getlist(key) | 以Python列表的形式返回参数key对应的所有值,如果key不存在则有一个空list 保证返回某个列表。 | |
setlist(key,list_) | 将 key 的值设置为 list_(而不是 __setitem__())。 | |
appendlist(key,item) | 将项目添加到与键关联的内部列表。 | |
setlistdefault(key, list) | 与 setdefault 略有不同,因为它接受列表而不是单个值作为参数。 | |
lists () | 略有不同与 items() 不同,它以列表的形式返回键的所有值,例如: >>> q = QueryDict('a=1&a=2&a=3') >>> q.lists() [('a', ['1', '2', '3'])] | |
urlencode() | 返回格式为 The string after 的查询字符串(例如"a=2&b=3&b=5"). |
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。