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

day64Django基础十之Form和ModelForm组件

Django基础十之Form和ModelForm组件本节目录一Form介绍二Form常用字段和插件三From所有内置字段四字段校验五Hook钩子方法六进阶补充七ModelForm八

Django基础十之Form和ModelForm组件

 

本节目录

  • 一 Form介绍
  • 二 Form常用字段和插件
  • 三 From所有内置字段
  • 四 字段校验
  • 五 Hook钩子方法
  • 六 进阶补充
  • 七 ModelForm
  • 八 xxx

一 Form介绍

  

  我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来。

  与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确。如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息.。

  Django form组件就实现了上面所述的功能。

  总结一下,其实form组件的主要功能如下:

    生成页面可用的HTML标签

    对用户提交的数据进行校验

    保留上次输入内容

  

  普通方式手写注册功能

    views.py

# 注册
def register(request):error_msg &#61; ""if request.method &#61;&#61; "POST":username &#61; request.POST.get("name")pwd &#61; request.POST.get("pwd")# 对注册信息做校验if len(username) <6:# 用户长度小于6位error_msg &#61; "用户名长度不能小于6位"else:# 将用户名和密码存到数据库return HttpResponse("注册成功")return render(request, "register.html", {"error_msg": error_msg})

 

    login.html






{% csrf_token %}

用户名:

密码&#xff1a;

{{ error_msg }}




 

  使用form组件实现注册功能

    views.py

      先定义好一个RegForm类&#xff1a;

from django import forms# 按照Django form组件的要求自己写一个类
class RegForm(forms.Form):name &#61; forms.CharField(label&#61;"用户名") #form字段的名称写的是什么&#xff0c;那么前端生成input标签的时候&#xff0c;input标签的name属性的值就是什么pwd &#61; forms.CharField(label&#61;"密码")

 

      再写一个视图函数&#xff1a;

# 使用form组件实现注册方式
def register2(request):form_obj &#61; RegForm()if request.method &#61;&#61; "POST":# 实例化form对象的时候&#xff0c;把post提交过来的数据直接传进去form_obj &#61; RegForm(data&#61;request.POST) #既然传过来的input标签的name属性值和form类对应的字段名是一样的&#xff0c;所以接过来后&#xff0c;form就取出对应的form字段名相同的数据进行form校验# 调用form_obj校验数据的方法if form_obj.is_valid():return HttpResponse("注册成功")return render(request, "register2.html", {"form_obj": form_obj})

 

    login2.html





#novalidate 告诉前端form表单&#xff0c;不要对输入的内容做校验{% csrf_token %}
#{{ form_obj.as_p }} 直接写个这个&#xff0c;下面的用户名和密码的标签不自己写&#xff0c;你看看效果

{{ form_obj.name }} {{ form_obj.name.errors.0 }} #errors是这个字段所有的错误&#xff0c;我就用其中一个错误提示就可以了&#xff0c;再错了再提示&#xff0c;并且不是给你生成ul标签了&#xff0c;单纯的是错误文本
{{ form_obj.errors }} #这是全局的所有错误&#xff0c;找对应字段的错误&#xff0c;就要form_obj.字段名
{{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}


 

 

    看网页效果发现 也验证了form的功能&#xff1a;
      前端页面是form类的对象生成的                                      -->生成HTML标签功能
      当用户名和密码输入为空或输错之后 页面都会提示        -->用户提交校验功能
      当用户输错之后 再次输入 上次的内容还保留在input框   -->保留上次输入内容

 

二 Form常用字段与插件

  

  创建Form类时&#xff0c;主要涉及到 【字段】 和 【插件】&#xff0c;字段用于对用户请求数据的验证&#xff0c;插件用于自动生成HTML;

  initial

    初始值&#xff0c;input框里面的初始值。

class LoginForm(forms.Form):username &#61; forms.CharField( min_length&#61;8,label&#61;"用户名",initial&#61;"张三" # 设置默认值)pwd &#61; forms.CharField(min_length&#61;6, label&#61;"密码")

 

  error_messages

    重写错误信息。

class LoginForm(forms.Form):username &#61; forms.CharField(min_length&#61;8,label&#61;"用户名",initial&#61;"张三",error_messages&#61;{"required": "不能为空","invalid": "格式错误","min_length": "用户名最短8位"})pwd &#61; forms.CharField(min_length&#61;6, label&#61;"密码")

 

  password

class LoginForm(forms.Form):...pwd &#61; forms.CharField(min_length&#61;6,label&#61;"密码",widget&#61;forms.widgets.PasswordInput(attrs&#61;{&#39;class&#39;: &#39;c1&#39;}, render_value&#61;True) #这个密码字段和其他字段不一样&#xff0c;默认在前端输入数据错误的时候&#xff0c;点击提交之后&#xff0c;默认是不保存的原来数据的&#xff0c;但是可以通过这个render_value&#61;True让这个字段在前端保留用户输入的数据)

 

  radioSelect

    单radio值为字符串

class LoginForm(forms.Form):username &#61; forms.CharField( #其他选择框或者输入框&#xff0c;基本都是在这个CharField的基础上通过插件来搞的min_length&#61;8,label&#61;"用户名",initial&#61;"张三",error_messages&#61;{"required": "不能为空","invalid": "格式错误","min_length": "用户名最短8位"})pwd &#61; forms.CharField(min_length&#61;6, label&#61;"密码")gender &#61; forms.fields.ChoiceField(choices&#61;((1, "男"), (2, "女"), (3, "保密")),label&#61;"性别",initial&#61;3,widget&#61;forms.widgets.RadioSelect())

 

  单选Select

class LoginForm(forms.Form):...hobby &#61; forms.fields.ChoiceField(choices&#61;((1, "篮球"), (2, "足球"), (3, "双色球"), ),label&#61;"爱好",initial&#61;3,widget&#61;forms.widgets.Select())

 

  多选Select

class LoginForm(forms.Form):...hobby &#61; forms.fields.MultipleChoiceField(choices&#61;((1, "篮球"), (2, "足球"), (3, "双色球"), ),label&#61;"爱好",initial&#61;[1, 3],widget&#61;forms.widgets.SelectMultiple())

 

  单选checkbox

class LoginForm(forms.Form):...keep &#61; forms.fields.ChoiceField(label&#61;"是否记住密码",initial&#61;"checked",widget&#61;forms.widgets.CheckboxInput())

 

  多选checkbox

class LoginForm(forms.Form):...hobby &#61; forms.fields.MultipleChoiceField(choices&#61;((1, "篮球"), (2, "足球"), (3, "双色球"),),label&#61;"爱好",initial&#61;[1, 3],widget&#61;forms.widgets.CheckboxSelectMultiple())

 

  choice字段注意事项

    在使用选择标签时&#xff0c;需要注意choices的选项可以配置从数据库中获取&#xff0c;但是由于是静态字段 获取的值无法实时更新&#xff0c;需要重写构造方法从而实现choice实时更新。

    方式一&#xff1a;

from django.forms import Form
from django.forms import widgets
from django.forms import fieldsclass MyForm(Form):user &#61; fields.ChoiceField(# choices&#61;((1, &#39;上海&#39;), (2, &#39;北京&#39;),),initial&#61;2,widget&#61;widgets.Select)def __init__(self, *args, **kwargs):super(MyForm,self).__init__(*args, **kwargs)# self.fields[&#39;user&#39;].choices &#61; ((1, &#39;上海&#39;), (2, &#39;北京&#39;),)# 或self.fields[&#39;user&#39;].choices &#61; models.Classes.objects.all().values_list(&#39;id&#39;,&#39;caption&#39;)

 

    方式二&#xff1a;

from django import forms
from django.forms import fields
from django.forms import models as form_modelclass FInfo(forms.Form):authors &#61; form_model.ModelMultipleChoiceField(queryset&#61;models.NNewType.objects.all()) # 多选# authors &#61; form_model.ModelChoiceField(queryset&#61;models.NNewType.objects.all()) # 单选

 

 

 

三 Form所有内置字段

 内置字段&#xff1a;

 内置字段

 

 

四 字段校验

 

  RegexValidator验证器

from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidatorclass MyForm(Form):user &#61; fields.CharField(validators&#61;[RegexValidator(r&#39;^[0-9]&#43;$&#39;, &#39;请输入数字&#39;), RegexValidator(r&#39;^159[0-9]&#43;$&#39;, &#39;数字必须以159开头&#39;)],)

 

  自定义验证函数

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError# 自定义验证规则
def 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;) #自定义验证规则的时候&#xff0c;如果不符合你的规则&#xff0c;需要自己发起错误class PublishForm(Form):title &#61; fields.CharField(max_length&#61;20,min_length&#61;5,error_messages&#61;{&#39;required&#39;: &#39;标题不能为空&#39;,&#39;min_length&#39;: &#39;标题最少为5个字符&#39;,&#39;max_length&#39;: &#39;标题最多为20个字符&#39;},widget&#61;widgets.TextInput(attrs&#61;{&#39;class&#39;: "form-control",&#39;placeholder&#39;: &#39;标题5-20个字符&#39;}))# 使用自定义验证规则phone &#61; fields.CharField(validators&#61;[mobile_validate, ],error_messages&#61;{&#39;required&#39;: &#39;手机不能为空&#39;},widget&#61;widgets.TextInput(attrs&#61;{&#39;class&#39;: "form-control",&#39;placeholder&#39;: u&#39;手机号码&#39;}))email &#61; fields.EmailField(required&#61;False,error_messages&#61;{&#39;required&#39;: u&#39;邮箱不能为空&#39;,&#39;invalid&#39;: u&#39;邮箱格式错误&#39;},widget&#61;widgets.TextInput(attrs&#61;{&#39;class&#39;: "form-control", &#39;placeholder&#39;: u&#39;邮箱&#39;}))

 

 

 

五 Hook钩子方法

 

  除了上面两种方式&#xff0c;我们还可以在Form类中定义钩子函数&#xff0c;来实现自定义的验证功能。

  局部钩子

    我们在Fom类中定义 clean_字段名() 方法&#xff0c;就能够实现对特定字段进行校验。

    举个例子&#xff1a;

class LoginForm(forms.Form):username &#61; forms.CharField(min_length&#61;8,label&#61;"用户名",initial&#61;"张三",error_messages&#61;{"required": "不能为空","invalid": "格式错误","min_length": "用户名最短8位"},widget&#61;forms.widgets.TextInput(attrs&#61;{"class": "form-control"}))...# 定义局部钩子&#xff0c;用来校验username字段,之前的校验股则还在&#xff0c;给你提供了一个添加一些校验功能的钩子def clean_username(self):value &#61; self.cleaned_data.get("username")if "666" in value:raise ValidationError("光喊666是不行的")else:return value

 

  全局钩子

    我们在Fom类中定义 clean() 方法&#xff0c;就能够实现对字段进行全局校验&#xff0c;字段全部验证完&#xff0c;局部钩子也全部执行完之后&#xff0c;执行这个全局钩子校验。

class LoginForm(forms.Form):...password &#61; forms.CharField(min_length&#61;6,label&#61;"密码",widget&#61;forms.widgets.PasswordInput(attrs&#61;{&#39;class&#39;: &#39;form-control&#39;}, render_value&#61;True))re_password &#61; forms.CharField(min_length&#61;6,label&#61;"确认密码",widget&#61;forms.widgets.PasswordInput(attrs&#61;{&#39;class&#39;: &#39;form-control&#39;}, render_value&#61;True))...# 定义全局的钩子&#xff0c;用来校验密码和确认密码字段是否相同&#xff0c;执行全局钩子的时候&#xff0c;cleaned_data里面肯定是有了通过前面验证的所有数据def clean(self):password_value &#61; self.cleaned_data.get(&#39;password&#39;)re_password_value &#61; self.cleaned_data.get(&#39;re_password&#39;)if password_value &#61;&#61; re_password_value:return self.cleaned_data #全局钩子要返回所有的数据else:self.add_error(&#39;re_password&#39;, &#39;两次密码不一致&#39;) #在re_password这个字段的错误列表中加上一个错误&#xff0c;并且clean_data里面会自动清除这个re_password的值&#xff0c;所以打印clean_data的时候会看不到它raise ValidationError(&#39;两次密码不一致&#39;)

 

 

 

六 进阶补充

 

  应用Bootstrap样式

    Django form应用Bootstrap样式简单示例&#xff1a;






{% csrf_token %}
{{ form_obj.username }}{{ form_obj.username.errors.0 }}
{{ form_obj.pwd }}{{ form_obj.pwd.errors.0 }}
{% for radio in form_obj.gender %}{% endfor %}




 

  批量添加样式

    可通过重写form类的init方法来实现。

class LoginForm(forms.Form):username &#61; forms.CharField(min_length&#61;8,label&#61;"用户名",initial&#61;"张三",error_messages&#61;{"required": "不能为空","invalid": "格式错误","min_length": "用户名最短8位"}...def __init__(self, *args, **kwargs):super(LoginForm, self).__init__(*args, **kwargs)for field in iter(self.fields):self.fields[field].widget.attrs.update({&#39;class&#39;: &#39;form-control&#39;})

 

 

七 ModelForm

 

  通常在Django项目中&#xff0c;我们编写的大部分都是与Django 的模型紧密映射的表单。 举个例子&#xff0c;你也许会有个Book 模型&#xff0c;并且你还想创建一个form表单用来添加和编辑书籍信息到这个模型中。 在这种情况下&#xff0c;在form表单中定义字段将是冗余的&#xff0c;因为我们已经在模型中定义了那些字段。

  基于这个原因&#xff0c;Django 提供一个辅助类来让我们可以从Django 的模型创建Form&#xff0c;这就是ModelForm。

  modelForm定义

    form与model的终极结合。

class BookForm(forms.ModelForm):class Meta:model &#61; models.Bookfields &#61; "__all__"labels &#61; {"title": "书名","price": "价格"}widgets &#61; {"password": forms.widgets.PasswordInput(attrs&#61;{"class": "c1"}),}

 

  class Meta下常用参数&#xff1a;

model &#61; models.Book # 对应的Model中的类
fields &#61; "__all__" # 字段&#xff0c;如果是__all__,就是表示列出所有的字段
exclude &#61; None # 排除的字段
labels &#61; None # 提示信息
help_texts &#61; None # 帮助提示信息
widgets &#61; None # 自定义插件
error_messages &#61; None # 自定义错误信息

 

  ModelForm的验证

    与普通的Form表单验证类型类似&#xff0c;ModelForm表单的验证在调用is_valid() 或访问errors 属性时隐式调用。

    我们可以像使用Form类一样自定义局部钩子方法和全局钩子方法来实现自定义的校验规则。

    如果我们不重写具体字段并设置validators属性的化&#xff0c;ModelForm是按照模型中字段的validators来校验的。

  save()方法

    每个ModelForm还具有一个save()方法。 这个方法根据表单绑定的数据创建并保存数据库对象。 ModelForm的子类可以接受现有的模型实例作为关键字参数instance&#xff1b;如果提供此功能&#xff0c;则save()将更新该实例。 如果没有提供&#xff0c;save() 将创建模型的一个新实例&#xff1a;

>>> from myapp.models import Book
>>> from myapp.forms import BookForm# 根据POST数据创建一个新的form对象
>>> form_obj &#61; BookForm(request.POST)# 创建书籍对象
>>> new_ book &#61; form_obj.save()# 基于一个书籍对象创建form对象
>>> edit_obj &#61; Book.objects.get(id&#61;1)
# 使用POST提交的数据更新书籍对象
>>> form_obj &#61; BookForm(request.POST, instance&#61;edit_obj)
>>> form_obj.save()

 

 

 

八 xxx

  

 

 

 

 

 

回到顶部


转:https://www.cnblogs.com/yanghongtao/p/10927924.html



推荐阅读
  • 前端技术分享——利用Canvas绘制鼠标轨迹
    作为一名前端开发者,我已经积累了Vue、React、正则表达式、算法以及小程序等方面的技能,但Canvas一直是我的盲区。因此,我在2018年为自己设定了一个新的学习目标:掌握Canvas,特别是如何使用它来创建CSS3难以实现的动态效果。 ... [详细]
  • 拖拉切割直线 ... [详细]
  • 深入解析Android Activity生命周期
    本文详细探讨了Android中Activity的生命周期,通过实例代码和详细的步骤说明,帮助开发者更好地理解和掌握Activity各个阶段的行为。 ... [详细]
  • 本文详细介绍了如何使用 HTML 和 CSS 实现一个具有动画效果的手风琴组件,包括代码示例和实现原理。 ... [详细]
  • MVC框架下使用DataGrid实现时间筛选与枚举填充
    本文介绍如何在ASP.NET MVC项目中利用DataGrid组件增强搜索功能,具体包括使用jQuery UI的DatePicker插件添加时间筛选条件,并通过枚举数据填充下拉列表。 ... [详细]
  • 本文介绍了如何在React Native应用中获取组件的实际宽度和高度,并详细说明了屏幕单位(如dp)与像素(px)之间的转换方法。 ... [详细]
  • 本文探讨了 Boost 库中的 Program Options 组件,这是一个强大的工具,用于解析命令行参数和配置文件。文章介绍了如何正确设置和使用该组件,包括处理复杂选项和负数值的方法。 ... [详细]
  • 本文详细介绍了在 Windows 7 上安装和配置 PHP 5.4 的 Memcached 分布式缓存系统的方法,旨在减少数据库的频繁访问,提高应用程序的响应速度。 ... [详细]
  • 在Android应用开发中,当在MenuItem中通过app:actionLayout属性使用Switch控件时,可能会遇到空指针异常的问题。本文将探讨该问题的原因及解决方案。 ... [详细]
  • 详解MyBatis二级缓存的启用与配置
    本文深入探讨了MyBatis二级缓存的启用方法及其配置细节,通过具体的代码实例进行说明,有助于开发者更好地理解和应用这一特性,提升应用程序的性能。 ... [详细]
  • 本文介绍了两个重要的Node.js库——cache-content-type和mime-types,它们在处理HTTP响应头时非常有用。cache-content-type是基于mime-types构建的,并且实现了缓存机制以提高性能。 ... [详细]
  • SpringBoot底层注解用法及原理
    2.1、组件添加1、Configuration基本使用Full模式与Lite模式示例最佳实战配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断配置类组 ... [详细]
  • 本文介绍了如何通过创建自定义 XML 文件来修改 Android 中 Spinner 的项样式,包括颜色和大小的调整。 ... [详细]
  • 本文详细介绍了跨站脚本攻击(XSS)的基本概念、工作原理,并通过实际案例演示如何构建XSS漏洞的测试环境,以及探讨了XSS攻击的不同形式和防御策略。 ... [详细]
  • 本文介绍了进程的基本概念及其在操作系统中的重要性,探讨了进程与程序的区别,以及如何通过多进程实现并发和并行。文章还详细讲解了Python中的multiprocessing模块,包括Process类的使用方法、进程间的同步与异步调用、阻塞与非阻塞操作,并通过实例演示了进程池的应用。 ... [详细]
author-avatar
123456q
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有