热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Django的form类

Django在表单中的角色处理表单是一件很复杂的事情。考虑一下Django的Admin站点,不同类型的大量数据项需要在一个表单中准备好、渲染成HTML、使用一个方便

Django 在表单中的角色

处理表单是一件很复杂的事情。考虑一下Django 的Admin 站点,不同类型的大量数据项需要在一个表单中准备好、渲染成HTML、使用一个方便的界面编辑、返回给服务器、验证并清除,然后保存或者向后继续处理。

Django 的表单功能可以简化并自动化大部分这些工作,而且还可以比大部分程序员自己所编写的代码更安全。

Django 会处理表单工作中的三个显著不同的部分:

准备数据、重构数据,以便下一步提交。
为数据创建HTML 表单
接收并处理客户端提交的表单和数据
可以手工编写代码来实现,但是Django 可以帮你完成所有这些工作。

在Django 中构建一个表单


Form 类

我们已经计划好了我们的 HTML 表单应该呈现的样子。在Django 中,我们的起始点是这里:

forms.py
from django import forms
class NameForm(forms.Form):your_name = forms.CharField(label='Your name', max_length=100)

它定义一个Form 类,只带有一个字段(your_name)。我们已经对这个字段使用一个友好的标签,当渲染时它将出现在

字段允许的最大长度通过max_length 定义。它完成两件事情。首先,它在HTML 的 上放置一个maxlength=”100” (这样浏览器将在第一时间阻止用户输入多于这个数目的字符)。它还意味着当Django 收到浏览器发送过来的表单时,它将验证数据的长度。

Form 的实例具有一个is_valid() 方法,它为所有的字段运行验证的程序。当调用这个方法时,如果所有的字段都包含合法的数据,它将:

返回True
将表单的数据放到cleaned_data 属性中。
完整的表单,第一次渲染时,看上去将像:

<label for&#61;"your_name">Your name: label>
"your_name" type&#61;"text" name&#61;"your_name" maxlength&#61;"100">

注意它不包含 标签和提交按钮。我们必须自己在模板中提供它们。

视图

发送给Django 网站的表单数据通过一个视图处理&#xff0c;一般和发布这个表单的是同一个视图。这允许我们重用一些相同的逻辑。

要操作一个通过URL发布的表单&#xff0c;我们要在视图中实例表单。

views.py

from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import NameFormdef get_name(request):# if this is a POST request we need to process the form dataif request.method &#61;&#61; &#39;POST&#39;:# create a form instance and populate it with data from the request:form &#61; NameForm(request.POST)# check whether it&#39;s valid:if form.is_valid():# process the data in form.cleaned_data as required# ...# redirect to a new URL:return HttpResponseRedirect(&#39;/thanks/&#39;)# if a GET (or any other method) we&#39;ll create a blank formelse:form &#61; NameForm()return render(request, &#39;name.html&#39;, {&#39;form&#39;: form})

如果访问视图的是一个GET 请求&#xff0c;它将创建一个空的表单实例并将它放置到要渲染的模板的上下文中。这是我们在第一次访问该URL 时预期发生的情况。

如果表单的提交使用POST 请求&#xff0c;那么视图将再次创建一个表单实例并使用请求中的数据填充它&#xff1a;form &#61; NameForm(request.POST)。这叫做”绑定数据至表单“&#xff08;它现在是一个绑定的表单&#xff09;。

我们调用表单的is_valid() 方法&#xff1b;如果它不为True&#xff0c;我们将带着这个表单返回到模板。这时表单不再为空&#xff08;未绑定&#xff09;&#xff0c;所以HTML 表单将用之前提交的数据填充&#xff0c;然后可以根据要求编辑并改正它。

如果is_valid() 为True&#xff0c;我们将能够在cleaned_data 属性中找到所有合法的表单数据。在发送HTTP 重定向给浏览器告诉它下一步的去向之前&#xff0c;我们可以用这个数据来更新数据库或者做其它处理。

模板

我们不需要在name.html 模板中做很多工作。最简单的例子是&#xff1a;

<form action&#61;"/your-name/" method&#61;"post">{% csrf_token %}{{ form }}<input type&#61;"submit" value&#61;"Submit" />
form>

根据{{ form }}&#xff0c;所有的表单字段和它们的属性将通过Django 的模板语言拆分成HTML 标记 。

表单和跨站请求伪造的防护

Django 原生支持一个简单易用的跨站请求伪造的防护。当提交一个启用CSRF 防护的POST 表单时&#xff0c;你必须使用上面例子中的csrf_token 模板标签。然而&#xff0c;因为CSRF 防护在模板中不是与表单直接捆绑在一起的&#xff0c;这个标签在这篇文档的以下示例中将省略。

HTML5 输入类型和浏览器验证

如果你的表单包含URLField、EmailField 或其它整数字段类型&#xff0c;Django 将使用url、email和 number 这样的HTML5 输入类型。默认情况下&#xff0c;浏览器可能会对这些字段进行它们自身的验证&#xff0c;这些验证可能比Django 的验证更严格。如果你想禁用这个行为&#xff0c;请设置form 标签的novalidate 属性&#xff0c;或者指定一个不同的字段&#xff0c;如TextInput。

现在我们有了一个可以工作的网页表单&#xff0c;它通过Django Form 描述、通过视图处理并渲染成一个HTML 。

这是你入门所需要知道的所有内容&#xff0c;但是表单框架为了便利提供了更多的内容。一旦你理解了上面描述的基本处理过程&#xff0c;你应该可以理解表单系统的其它功能并准备好学习更多的底层机制。

拓展应用

required&#xff1a;是否可以为空。required&#61;True 不可以为空&#xff0c;required&#61;False 可以为空
max_length&#61;4 最多4个值&#xff0c;超过不会显示
min_length&#61;2 至少两个值&#xff0c;少于两个会返回提示信息
error_messages&#61;{‘required’: ‘邮箱不能为空’, ‘invalid’: ‘邮箱格式错误’} 自定义错误信息&#xff0c;invalid 是格式错误
widget&#61;forms.TextInput(attrs&#61;{‘class’: ‘c1’}) 给自动生成的input标签自定义class属性
widget&#61;forms.Textarea() 生成Textarea标签。widget默认生成input标签

实战

models.py

from django.db import models
class Author(models.Model):"""作者"""name &#61; models.CharField(max_length&#61;100)age &#61; models.IntegerField()class BookType(models.Model):"""图书类型"""caption &#61; models.CharField(max_length&#61;64)class Book(models.Model):"""图书"""name &#61; models.CharField(max_length&#61;64)pages &#61; models.IntegerField()price &#61; models.DecimalField(max_digits&#61;10,decimal_places&#61;2)pubdate &#61; models.DateField()authors &#61; models.ManyToManyField(Author)book_type &#61; models.ForeignKey(BookType)

forms.py&#xff1a;

from django import forms
from app01 import modelsclass Form1(forms.Form):user &#61; forms.CharField(label&#61;&#39;Your name&#39;,widget&#61;forms.TextInput(attrs&#61;{&#39;class&#39;: &#39;c1&#39;}),error_messages&#61;{&#39;required&#39;: &#39;用户名不能为空&#39;}, )pwd &#61; forms.CharField(max_length&#61;4, min_length&#61;2, required&#61;True,error_messages &#61; {&#39;required&#39;: &#39;密码不能为空&#39;})email &#61; forms.EmailField(error_messages&#61;{&#39;required&#39;: &#39;邮箱不能为空&#39;, &#39;invalid&#39;: &#39;邮箱格式错误&#39;})memo &#61; forms.CharField(widget&#61;forms.Textarea(),error_messages&#61;{&#39;required&#39;: &#39;memo不能为空&#39;})vip_type &#61; ((0, u&#39;普通用户&#39;),(1, u&#39;高级用户&#39;),)vip &#61; forms.CharField(widget&#61;forms.widgets.Select(choices&#61;vip_type, attrs&#61;{&#39;class&#39;: &#39;form-control&#39;}))#写上以下代码就不用担心数据库添加了数据而不能及时获取了def __init__(self, *args, **kwargs):#每次创建Form1对象时执行init方法super(Form1, self).__init__(*args, **kwargs)self.fields[&#39;book_type&#39;] &#61; forms.CharField(widget&#61;forms.widgets.Select(choices&#61;models.BookType.objects.values_list(&#39;id&#39;, &#39;caption&#39;),attrs&#61;{&#39;class&#39;: "form-control"}))

HTML&#xff1a;

<html lang&#61;"en">
<head><meta charset&#61;"UTF-8"><title>Titletitle>
<style>.input-group{position: relative;padding: 20px;width: 250px;}.input-group input{width: 200px;display: inline-block;}.inline-group span{display: inline-block;position: absolute;height: 12px;font-size: 8px;border: 1px solid red;background-color: coral;color: white;top: 41px;left: 20px;width: 202px;}style>
head>
<body><form action&#61;"/form1/" method&#61;"POST">{% csrf_token %}
<div class&#61;"input-group">
<label>用户名:label>{{ form.user }}<span>{{ form.user.errors }}span>
div><div class&#61;"input-group">
<label>密码:label>{{ form.pwd }}<span>{{ form.pwd.errors }}span>
div><div class&#61;"input-group">
<label>邮箱:label>{{ form.email }}<span>{{ form.email.errors }}span>
div><div class&#61;"input-group">
<label>memo:label>{{ form.memo }}<span>{{ form.memo.errors }}span>
div>
<div class&#61;"input-group">
<label>会员等级:label>{{ form.vip }}<span>{{ form.vip.errors }}span>
div>
<div><input type&#61;"submit" value&#61;"提交" />
div>form>body>
html>

views.py

from django.shortcuts import render,HttpResponse
from app01.forms import Form1
from app01.models import *def form1(request):if request.method &#61;&#61; "POST":f &#61; Form1(request.POST)if f.is_valid():print(f.cleaned_data)else:return render(request,"account/form1.html",{"error":f.errors,"form":f})else:# 如果不是post提交数据&#xff0c;就不传参数创建对象&#xff0c;并将对象返回给前台&#xff0c;直接生成input标签&#xff0c;内容为空f &#61; Form1()return render(request,"account/form1.html",{"form":f})return render(request,"account/form1.html")

Django里面没有手机验证&#xff0c;没有的需要自定义

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
from django.core.exceptions import ValidationErrordef mobile_validate(value):mobile_re &#61; re.compile(r&#39;^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$&#39;)if not mobile_re.match(value):raise ValidationError(&#39;手机号码格式错误&#39;)class PublishForm(forms.Form):user_type_choice &#61; ((0, u&#39;普通用户&#39;),(1, u&#39;高级用户&#39;),)user_type &#61; forms.IntegerField(widget&#61;forms.widgets.Select(choices&#61;user_type_choice,attrs&#61;{&#39;class&#39;: "form-control"}))title &#61; forms.CharField(max_length&#61;20,min_length&#61;5,error_messages&#61;{&#39;required&#39;: u&#39;标题不能为空&#39;,&#39;min_length&#39;: u&#39;标题最少为5个字符&#39;,&#39;max_length&#39;: u&#39;标题最多为20个字符&#39;},widget&#61;forms.TextInput(attrs&#61;{&#39;class&#39;: "form-control",&#39;placeholder&#39;: u&#39;标题5-20个字符&#39;}))memo &#61; forms.CharField(required&#61;False,max_length&#61;256,widget&#61;forms.widgets.Textarea(attrs&#61;{&#39;class&#39;: "form-control no-radius", &#39;placeholder&#39;: u&#39;详细描述&#39;, &#39;rows&#39;: 3}))phone &#61; forms.CharField(validators&#61;[mobile_validate, ],error_messages&#61;{&#39;required&#39;: u&#39;手机不能为空&#39;},widget&#61;forms.TextInput(attrs&#61;{&#39;class&#39;: "form-control",&#39;placeholder&#39;: u&#39;手机号码&#39;}))email &#61; forms.EmailField(required&#61;False,error_messages&#61;{&#39;required&#39;: u&#39;邮箱不能为空&#39;,&#39;invalid&#39;: u&#39;邮箱格式错误&#39;},widget&#61;forms.TextInput(attrs&#61;{&#39;class&#39;: "form-control", &#39;placeholder&#39;: u&#39;邮箱&#39;}))def publish(request):ret &#61; {&#39;status&#39;: False, &#39;data&#39;: &#39;&#39;, &#39;error&#39;: &#39;&#39;, &#39;summary&#39;: &#39;&#39;}if request.method &#61;&#61; &#39;POST&#39;:request_form &#61; PublishForm(request.POST)if request_form.is_valid():request_dict &#61; request_form.clean()print request_dictret[&#39;status&#39;] &#61; Trueelse:error_msg &#61; request_form.errors.as_json()ret[&#39;error&#39;] &#61; json.loads(error_msg)return HttpResponse(json.dumps(ret))


推荐阅读
  • Android 图像色彩处理技术详解
    本文详细探讨了 Android 平台上的图像色彩处理技术,重点介绍了如何通过模仿美图秀秀的交互方式,利用 SeekBar 实现对图片颜色的精细调整。文章展示了具体的布局设计和代码实现,帮助开发者更好地理解和应用图像处理技术。 ... [详细]
  • Spring框架入门指南:专为新手打造的详细学习笔记
    Spring框架是Java Web开发中广泛应用的轻量级应用框架,以其卓越的功能和出色的性能赢得了广大开发者的青睐。本文为初学者提供了详尽的学习指南,涵盖基础概念、核心组件及实际应用案例,帮助新手快速掌握Spring框架的核心技术与实践技巧。 ... [详细]
  • 在处理大规模并发请求时,传统的多线程或多进程模型往往无法有效解决性能瓶颈问题。尽管它们在处理小规模任务时能提升效率,但在高并发场景下,系统资源的过度消耗和上下文切换的开销会显著降低整体性能。相比之下,Python 的 `asyncio` 模块通过协程提供了一种轻量级且高效的并发解决方案。本文将深入解析 `asyncio` 模块的原理及其在实际应用中的优化技巧,帮助开发者更好地利用协程技术提升程序性能。 ... [详细]
  • 深入解析Wget CVE-2016-4971漏洞的利用方法与安全防范措施
    ### 摘要Wget 是一个广泛使用的命令行工具,用于从 Web 服务器下载文件。CVE-2016-4971 漏洞涉及 Wget 在处理特定 HTTP 响应头时的缺陷,可能导致远程代码执行。本文详细分析了该漏洞的成因、利用方法以及相应的安全防范措施,包括更新 Wget 版本、配置防火墙规则和使用安全的 HTTP 头。通过这些措施,可以有效防止潜在的安全威胁。 ... [详细]
  • Android目录遍历工具 | AppCrawler自动化测试进阶(第二部分):个性化配置详解
    终于迎来了“足不出户也能为社会贡献力量”的时刻,但有追求的测试工程师绝不会让自己的生活变得乏味。与其在家消磨时光,不如利用这段时间深入研究和提升自己的技术能力,特别是对AppCrawler自动化测试工具的个性化配置进行详细探索。这不仅能够提高测试效率,还能为项目带来更多的价值。 ... [详细]
  • 深入解析 UIImageView 与 UIImage 的关键细节与应用技巧
    本文深入探讨了 UIImageView 和 UIImage 的核心特性及应用技巧。首先,详细介绍了如何在 UIImageView 中实现动画效果,包括创建和配置 UIImageView 实例的具体步骤。此外,还探讨了 UIImage 的加载方式及其对性能的影响,提供了优化图像显示和内存管理的有效方法。通过实例代码和实际应用场景,帮助开发者更好地理解和掌握这两个重要类的使用技巧。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • 使用 Python 中的 Matplotlib Axes 获取标签方法详解 ... [详细]
  • HTTP请求与响应机制:基础概览
    在Web浏览过程中,HTTP协议通过请求和响应报文实现客户端与服务器之间的通信。当用户访问一个网页时,浏览器会发送一个HTTP请求报文至服务器,服务器接收到请求后,会生成并返回一个HTTP响应报文。这两种报文均包含三个主要部分:起始行、头部字段和消息体,确保了数据的有效传输和解析。 ... [详细]
  • 成功实现Asp.Net MVC3网站与MongoDB数据库的高效集成
    我们成功地构建了一个基于Asp.NET MVC3框架的网站,并实现了与MongoDB数据库的高效集成。此次更新不仅完善了基本的创建和显示功能,还全面实现了数据的增删改查操作。在创建功能方面,我们修复了之前代码中的错误,确保每个属性都能正确生成。此外,我们还对数据模型进行了优化,以提高系统的性能和稳定性。 ... [详细]
  • 技术日志:深入探讨Spark Streaming与Spark SQL的融合应用
    技术日志:深入探讨Spark Streaming与Spark SQL的融合应用 ... [详细]
  • Java新手求助:如何优雅地向心仪女生索要QQ联系方式(附代码示例与技巧)
    在端午节后的闲暇时光中,我无意间在技术社区里发现了一篇关于如何巧妙地向心仪女生索取QQ联系方式的文章,顿时感到精神焕发。这篇文章详细介绍了源自《啊哈!算法》的方法,不仅图文并茂,还提供了实用的代码示例和技巧,非常适合 Java 新手学习和参考。 ... [详细]
  • 在Laravel中实现PHP对JSON数据的发布与处理 ... [详细]
  • 表面缺陷检测数据集综述及GitHub开源项目推荐
    本文综述了表面缺陷检测领域的数据集,并推荐了多个GitHub上的开源项目。通过对现有文献和数据集的系统整理,为研究人员提供了全面的资源参考,有助于推动该领域的发展和技术进步。 ... [详细]
  • 本文探讨了在Android应用中实现动态滚动文本显示控件的优化方法。通过详细分析焦点管理机制,特别是通过设置返回值为`true`来确保焦点不会被其他控件抢占,从而提升滚动文本的流畅性和用户体验。具体实现中,对`MarqueeText.java`进行了代码层面的优化,增强了控件的稳定性和兼容性。 ... [详细]
author-avatar
michael
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有