Django form组件 - 神奇的后端直接渲染HTML

这篇具有很好参考价值的文章主要介绍了Django form组件 - 神奇的后端直接渲染HTML。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

之前在HTML页面中利用form表单向后端提交数据时会写一些获取用户输入的标签并且使用form标签将其包裹起来。并且很多场景下都需要对用户的输入做校验,比如用户输入的长度和格式等,如果用户输入的有误就需要在页面上相应的位置显示相应的错误信息。而django form组件实现了上面所述的功能。

form组件功能

总结起来,django from组件的主要功能有以下三点:

①生成页面可用的HTML标签;

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

③保留上次输入的内容。

form组件基本使用

form组件的使用和django模型非常类似,现在应用下的views.py中定义好form类,代码如下:

# views.py
from django import forms
class MyForm(forms.Form):
    '''
    # username字符串类型最小3位最大8位
	# password字符串类型最小3位最大8位
	# email字段必须符合邮箱格式  xxx@xx.com
	# label属性用来指定字段展示信息
    '''
    # username字符串类型,最小3位,最大8位
    username = forms.CharField(max_length=8,min_length=3, lable='用户名')
    # password,字符串类型,最小3位,最大8位
    password = forms.CharField(max_length=8,min_length=3, lable='密码')
    # email字段必须符合邮箱格式
    email = forms.EmailField(lable='邮箱')

测试form组件的环境也有两种方式,一种方式同样是通过test.py,另一种方式就是通过pycharm的测试环境Python console,这里采用第二种方式进行测试。

# 1 导入需要测试的文件
from first import views

# 2 将需要校验的数据组织成字典的形式传入自定义的form类进行校验
form_obj = views.MyForm({'username':'python',,'emali':'123'})

# 3 判断数据是否合法:注意该方法只有在所有的数据全部合法的情况下才会返回True
form_obj.is_valid()  # False

# 4 查看所有通过校验的数据
form_obj.cleaned_data  # {'username': 'python', }

# 5 查看所有不符合校验规则的字段和不符合原因,错误原因是列表,因为可能错误原因有多个
form_obj.errors  # {'email': ['Enter a valid email address.']}

# 6 如果校验数据中出现了类中没有的字段,forms组件只会校验存在的字段,不存在的字段传了直接忽略
form_obj = views.MyForm({'username':'python',,'emali':'123@qq.com','hobby':'read'})
form_obj.is_valid()  # True

# 7 默认情况下,类里面所有的字段都必须传值,也就意味着校验数据的时候,默认情况下数据可以多传但是不能少传
form_obj = views.MyForm({'username':'jason',})
form_obj.is_valid()  # False

form组件的校验规则可以总结出以下方法:

给MyForm传值实例化对象,传值方式:将带校验的字段和数据组织成字典的形式
is_valid()		该方法只有在所有的数据全部合法的情况下才会返回True
cleaned_data	查看所有校验通过的数据
errors			查看所有不符合校验规则以及不符合的原因,{key: ['']}
has_error()		判断某一个字段是否不合法,不合法返回True

校验数据只校验类中出现的字段,多传不影响,多传的字段直接忽略
校验数据 默认情况下 类里面所有的字段都必须传值,即少传肯定不合法

form组件渲染标签

上面提到form组件可以自动帮忙渲染获取用户输入的标签(input select radio checkbox),但是不能自动渲染提交按钮,那么是如何实现的呢?首先是后端的代码,在views.py中书写视图函数:

# views.py
def index(request):
    # 先产生一个空对象
    form_obj = MyForm()
    
    if request.method == 'POST':
        # 获取用户数据进行校验,如果一条一条的获取用户数据太过繁琐,而且校验数据需要字典格式,而request.POST获取到的数据格式就是queryset——dict对象
        form_obj = MyForm(request.POST)
        # 如果数据合法应该操作数据库,这里先简写
        if form_obj.is_valid():
            return HttpResponse('OK')
        
    # 如果是get请求返回直接将空对象传递给html页面
    return render(request,'register.html',locals())

如果数据不合法需要将错误信息展示到前端,那么如何将错误信息展示到前端呢?因为form校验产生的错误信息就是字典格式,到前端就是自定义对象,所以可以通过前端点点点的方式,下面是前端register.html页面

<body>
<form action="" method="post" novalidate>  <!--novalidate参数阻止浏览器自动校验-->
    {% for form in form_obj %}
        <p>
            {{ form.label }} : {{ form }}
        <!--span是预留的展示错误信息的标签,form.errors.0的意思是只展示第一条错误提示,否则forms组件会将错误信息展示成无序列表的形式-->
        <span style="color: red">{{ form.errors.0 }}</span>
        </p>

    {% endfor %}
    <input type="submit">
</form>
</form>
</body>

错误信息在前端显示都是英文的,能不能改成中文的呢?可以通过参数error_messages来自定制错误信息。

class MyForm(forms.Form):
    '''
    error_messages参数需要构造成字典的数据结构,key是校验条件,value是校验失败时的提示信息
    '''
    username = forms.CharField(min_length=5,
                               max_length=12,
                               label='用户名',
                               error_messages={
                                   'min_length': '用户名不能少于5位',
                                   'max_length': '用户名不能超多12位',
                                   'required': '用户名不能为空',
                               }
                               )
    password = forms.CharField(min_length=6, max_length=12, label='密码')
    re_password = forms.CharField(min_length=6, max_length=12, label='确认密码')
    email = forms.EmailField(label='邮箱')

HOOK钩子函数

上述form组件的基本使用只是对数据的第一层校验,很多时候对参数还需要一些特殊的校验规则,这时候就可以使用钩子函数,钩子函数在form组件中类似于第二道校验,能够让我们自定义校验规则,校验流程通过第一层校验之后就会来到钩子函数,可以在钩子函数中进一步定制校验规则,钩子函数分为两种分别是局部钩子和全局钩子,钩子函数定义在form类中。

局部钩子

当需要给单个字段增加校验规则的时候就可以使用局部钩子了。比如规定用户名中不能包含hook

# views.py
class MyForm(forms.Form):
    username = forms.CharField(min_length=5,
                               max_length=12,
                               label='用户名',
                               error_messages={
                                   'min_length':'用户名不能少于5位',
                                   'max_length':'用户名不能超多12位',
                                   'required':'用户名不能为空',
                               })

    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '666' in username:
            self.add_error('username', '中包含了hook')
        return username

定义局部钩子函数可以总结为以下几点:

①局部钩子的函数名为:clean_字段(),字段就是自定义校验规则的字段;

②该方法中在cleaned_data中获取该字段的数据,局部钩子中只能拿到当前字段的数据;

③校验数据失败时,通过add_error方法给字段添加错误信息;

④局部钩子取出的字段数据一定要返回出去。

全局钩子

当需要给多个字段增加校验规则的时候可以使用全局钩子。比如校验两次密码输入是否一致:

# views.py
class MyForm(forms.Form):
    
    password = forms.CharField(min_length=6, max_length=12, label='密码')
    re_password = forms.CharField(min_length=6, max_length=12, label='确认密码')
   
    def clean(self):
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('re_password')
        if password != re_password:
            self.add_error('re_password', '两次密码输入不一致')

        return self.cleaned_data

定义全局钩子函数可以总结为以下几点:

①全局钩子可以在cleaned_data内获得任意字段的数据;

②全局钩子取出的cleaned_data一定要返回出去。

form组件参数介绍

首先是常用参数:

min_length			最少几位字符
max_length			最多几位字符
label				字段名
required  			控制字段是否必填(默认required=True)
error_messages  	自定义报错信息,字典的结构
initial  			初始值,input框里面的初始值value

HTML页面上的标签可以修改属性,那么form组件是直接渲染的,如何修改标签的属性呢?就是通过widget参数,通过该参数可以修改标签的属性。

class MyForm(forms.Form):
    username = forms.CharField(min_length=5,
                               max_length=12,
                               widget=forms.widgets.TextInput(attrs={'class': 'form-control'}))

"""
总结:
widget=forms.widgets.TextInput()默认是TextInput(及input[type='text'])
widget=forms.widgets.PasswordInput()密码格式
widget=forms.widgets.EmailInput()邮箱格式

attrs提供字段的属性,可以是内置的也可以是自定义的;如有多个class:空格隔开即可。
"""

另外在第一道校验规则中,还支持正则校验,就是通过validators参数进行正则校验:

from django import forms
from django.core.validators import RegexValidator

class MyForm(forms.Form):
 
    phone = forms.CharField(label='手机号',
                            validators=[
                                RegexValidator(r'^[0-9]+$', '请输入数字'),
                                RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
                            ],)
   
"""
总结:
validators的值是一个列表,烈面可以更多个正则表校验条件
RegexValidator第一个参数是正则表校验条件,第二个是校验失败是的提示信息

"""

form组件其他标签渲染

form组件不止能对input框进行渲染,也支持对radio select checkbox标签进行渲染:

# radio单选
gender = forms.ChoiceField(
    choices=((1, "男"), (2, "女"), (3, "保密")),
    label="性别",
    initial=1,
    widget=forms.widgets.RadioSelect()
)

# checkbox多选
hobby = forms.MultipleChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=[1, 3],
    widget=forms.widgets.CheckboxSelectMultiple()
)


# 下拉单选:即使添加attrs={'multiple': 'multiple'}任然为单选
hobby2 = forms.ChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好",
    initial=3,
    widget=forms.widgets.Select()
)

# 下拉多选
hobby3 = forms.MultipleChoiceField(
    choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
    label="爱好2",
    initial=[1, 3],
    widget=forms.widgets.SelectMultiple()
)

# 选择checkbox是否选择, initial空表示False, 只要有值就是True默认选中(任何值都可以)
keep = forms.ChoiceField(
    choices=(('False', 0), ('True', 1)),
    label="是否记住密码",
    initial='',
    widget=forms.widgets.CheckboxInput()
)

在使用choice参数时如果choices展示的数据是动态从数据库中获取的,还需要额外的设置:文章来源地址https://www.toymoban.com/news/detail-432220.html

class BookAddForm(forms.Form):
    name = forms.CharField(label='图书名称',
                           error_messages={'required': '图书名称不能为空'},
                           widget=forms.widgets.TextInput())
    
    price = forms.DecimalField(label='价格',
                               error_messages={'required': '图书价格不能为空'},
                               widget=forms.widgets.TextInput())
    
    publish_date = forms.DateField(label='出版日期',
                                   error_messages={'required': '出版日期不能为空'},
                                   widget=forms.widgets.DateInput())
    
    publish_id = forms.ChoiceField(label='出版社',
                                   error_messages={'required':'出版社不能为空'},
                                   widget=forms.widgets.Select())
    
    author = forms.MultipleChoiceField(label='作者',
                                       error_messages={'required':'作者不能为空'},
                                       widget=forms.widgets.SelectMultiple())

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # choices字段的数据动态来自数据库
        self.fields['publish_id'].choices = models.Publish.objects.values_list('pk', 'name')
        self.fields['author'].choices = models.Author.objects.values_list('pk', 'name')

到了这里,关于Django form组件 - 神奇的后端直接渲染HTML的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【react】记录一次react组件props依赖异步数据(setFieldsValue)后传递form给子组件,再逐层传递给孙子组件引起的未渲染异常

    背景 react祖父组件设置异步数据(setFieldsValue)后传递form给子组件,再逐层传递给孙子组件引起的未渲染异常,孙子组件如果不设置useEffect和useState去监听value的值进行重渲染,会出现获取得到value最新值,但是不进行渲染的异常 解决前后的代码对比 完整代码(异常): 完整

    2024年01月17日
    浏览(35)
  • vue3 组合式 ant.design组件Table嵌套表格,从后端获取数据并动态渲染

    在根据官方文档使用ant.design中的嵌套表格时,发现官方文档很多地方都不够详细。在过程中踩了不少坑,例如: 子表如何获取父表的数据? 如何获取子表的行索引? 如何让子表的数据源来自父表该行的数据? 总之,最后还是磕磕绊绊做完了功能,于是第一时间把代码整理

    2024年02月15日
    浏览(28)
  • 构建WebRTC技术需要的后端服务

    📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香! 📢本文作者:由webmote 原创 📢作者格言:新的征程,我们面对的不是技术而是人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 ! 当下直播界最炙手可热的技术,

    2024年02月15日
    浏览(34)
  • 怎样成为优秀的后端工程师

    本文翻译自国外论坛 medium,原文地址:https://medium.com/@pradeesh-kumar/how-to-become-a-good-backend-engineer-9da75202a104 让我们一起看看国外开发者认为优秀后端工程师需要掌握哪些技能。 本质上,软件开发有两个要素:前端和后端。当访问者登陆网站时,他们会看到 UI 与之交互,即前端

    2024年02月03日
    浏览(34)
  • 汇编代码生成和编译器的后端

    基于SLR(1)分析的语义分析及中间代码生成程序-CSDN博客 https://blog.csdn.net/lijj0304/article/details/135097554?spm=1001.2014.3001.5501 在前面编译器前端实现的基础上,将所生成的中间代码翻译成某种目标机的汇编代码,实现编译器后端实现的任务。然后进一步实现程序的输入是源程序,输出

    2024年01月21日
    浏览(37)
  • 博客系统的后端设计(八) - 实现发布博客功能

    在原来的编辑页面点击发布文章按钮,是不会有什么效果的。 这是因为此时还不能实现前后端的交互。 请求使用 POST ,路径是 /blog title=这是标题content=这是正文 请求中要有 body,按照 form 表单的方式添加进去。 响应使用 HTTP/1.1 302 跳转到列表页:Location: blog.list.html 在一篇博

    2024年02月07日
    浏览(34)
  • 基于模块自定义扩展字段的后端逻辑实现(一)

    目录 一:背景介绍 二:实现过程 三:字段标准化 四:数据存储 五:数据扩展 六:表的设计 一:背景介绍   最近要做一个系统,里面涉及一个模块是使用拖拉拽的形式配置模块使用的字段表单,主要包括新建/编辑模块,模块详情等。这里涉及的重点是新建模块的表单是手

    2024年02月02日
    浏览(25)
  • Node.js与TypeScript:优雅的后端开发方式

    随着前端 JavaScript语言的不断发展, Node.js 开发环境也越来越受到开发者们的欢迎。 Node.js 让我们可以轻松地使用 JavaScript 来编写服务器端应用,从而实现前后端一致的开发体验。在 Node.js 的发展历程中, TypeScript 也逐渐成为了一种备受欢迎的编程语言,它的出现大大提高了

    2024年02月10日
    浏览(55)
  • 为什么 OpenAI 团队采用 Python 开发他们的后端服务?

    Python,年龄可能比很多读者都要大,但是它在更新快速的编程界却一直表现出色,甚至有人把它比作是编程界的《葵花宝典》,只是Python的速成之法相较《葵花宝典》有过之而无不及。 Python简洁,高效的特点,大大提升了程序员的编码速度,极大的提高了程序员的办公效率,

    2024年02月02日
    浏览(36)
  • 做了8年前端,感谢那些优秀的后端,陪伴我工作,教会我成长

    ☆ 前段时间由于一时的头脑发热,写了一篇《做了8年前端,细说那些曾经让你浴霸不能的后端》的博客,虽然每个细节也都属实吧,但始终是一些负能量的东西,建议大家不要去看了,今年互联网情况已经这样了,就不要再去怀念那些不美好了 ☆ 干了这么多年前端,怎么可

    2024年02月21日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包