【form组件】

 

需求:
  写一个注册功能
  获取用户名和密码 利用form表单提交数据
  在后端判断用户和密码是否符合一定的条件
    用户名中不能含有大傻子
    密码不能少于三位数
  如果符合条件,然后将提示信息展示到页面前端

 

 

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <script src="/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
 7     <link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.min.css">
 8 </head>
 9 <body>
10 <form action="" method="post">
11     <p>username:
12         <input type="text" name="username">
13         <span style="color: red">{{ back_dic.username }}</span>
14     </p>
15     <p>password:<input type="text" name="password">
16         <span style="color: blue">{{ back_dic.password }}</span>
17     </p>
18     <input type="submit" value="提交" class="btn btn-info">
19 
20 </form>
21 </body>
22 </html>

然而form组件替我们省去了这些步骤,

form能够完成的事情:

  1.渲染html代码

  2.检验数据

  3.展示提示信息

 

 

 

(数据的校验)

1 为什么数据校验非要在后端而不利用前端的js直接完成呢?
2     数据校验前端可以可无,但是后端必须要有
3     且前端的校验是弱不禁风的,可以直接修改,或是利用爬虫程序绕过前端页面直接朝后端提交数据,
4     所以在后端校验数据比较好
5 
6 -------------------
7 测试环境的准备:
8     1.可以自己拷贝代码准备
9     2.在pycharm里面其实也有一个准备好的测试环境---python Console

(校验的内部本质)

 

1  问题:多写了字段为什么返回的是True?
2 
3   原因:校验数据只校验类里面有的字段,多传的字段不校验
4 
5  问题2:少传字段返回什么?
6  
7    不可以,返回false,原因必须传值

 

(views,py)

 

(必须完全符合需求才能返回True)

 

 

[渲染html标签,不会渲染提交按钮]

 

 。

【展示错误信息提示】

一些字段意思

1 label    字段名
2 error_messages 错误提示信息
3 initial    初始值,默认值
4 required    是否必填   /require=false
5 widget=forms.widgets.TextInput(attrs={'class': 'form-control c1 c2'})     控制类型样式
6 第一道关卡还支持正则校验
7     validators=[RegexValidator(r'^1\d{10}$', '手机格式错误')]
  
  
phone = forms.CharField(
validators=
[RegexValidator(r'^1[3-9]\d{9}$', '手机格式错误'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
],
)

 

views.py

# form组件校验信息
from django import forms


class MyForm(forms.Form):
    # 字符串类型,错误信息提示为中文:error_messages+{错误类型解释}
    username = forms.CharField(min_length=3, max_length=8, label='用户名',
                               error_messages={
                                   'required': '用户名不能为空',
                                   'min_length': '用户名长度不能小于3',
                                   'max_length': '用户名长度不能大于8',
                               })
    password = forms.CharField(min_length=3, max_length=8, label='密码')
    # email必须符合邮箱格式
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                 'required': '邮箱不能为空',
                                 'invalid': '邮箱格式错误',
                             })


# 渲染html页面
def index(request):
    # 1.先产生一个空对象
    form_obj = MyForm()
    # 展示错误信息提示
    if request.method == 'POST':
        # 2.获取用户数据并校验,技能解决获取数据繁琐,也能解决检验数据需要的字典格式
        # 1和2步骤的名称一定要一样
        form_obj = MyForm(request.POST)
        # 判断数据是否合法
        if form_obj.is_valid():
            # 如果合法操作数据库
            return HttpResponse('ok')
        # 不合法,展示错误信息到前端页面
    # 3.直接将该空对象直接传个html页面
    return render(request, 'index.html', locals())

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
<script src="/static/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.min.css">
{% block css %}
    {% endblock %}
</head>
<body>
{#novalidate:浏览器不校验#}
<form action="" method="post" novalidate>


    <p>第三种渲染方式:两者的结合</p>
    {% for form in form_obj %}
        <p>{{ form.label }}:{{ form }}
{#            提示错误信息框:这时浏览器自动帮我们校验数据,不好#}
{#            form.errors.0:只拿到第一个错误信息,变成p便签#}
            <span style="color: red">{{ form.errors.0 }}</span>
        </p>
    {% endfor %}
    <input type="submit" class="btn btn-info">

</form>
</body>
</html>

 总结:

  

 。

【form组件钩子函数:HOOK*****】

1 钩子函数:
2     在特定的节点自动触发完成的响应操作
3     钩子函数在form组件中就类似于第二道关卡,能够让我们自定义校验规则
4 
5 在form组件中有两类钩子
6     1.局部钩子
7             当需要给单个字段增加校验规则的时候可以使用
8     2.全局钩子
9             当需要给多个个字段增加校验规则的时候可以使用

 

 

 views.py
class
MyForm(forms.Form): # 字符串类型 username = forms.CharField(min_length=3, max_length=8, label='用户名', error_messages={ 'required': '用户名不能为空', 'min_length': '用户名长度不能小于3', 'max_length': '用户名长度不能大于8', }) password = forms.CharField(min_length=3, max_length=8, label='密码') re_password = forms.CharField(min_length=3, max_length=8, label='确认密码', error_messages={ 'required': '确认密码不能为空', 'min_length': '确认密码长度不能小于3', 'max_length': '确认密码长度不能大于8', }) # email必须符合邮箱格式 email = forms.EmailField(label='邮箱', error_messages={ 'required': '邮箱不能为空', 'invalid': '邮箱格式错误', }) ****************************************************************************钩子函数校验 # 钩子函数,只有第一道验证全部通过,才会执行钩子函数 # 局部钩子 def clean_username(self): username = self.cleaned_data.get('username') if '666' in username: # 添加错误信息展示 self.add_error('username', '用户名不能包含666') # 将钩子函数勾出来的数据再放回去 return username # 全局钩子 def clean(self): # 获取两个字段 password=self.cleaned_data.get('password') re_password=self.cleaned_data.get('re_password') if not password == re_password: self.add_error('re_password', '两次密码不一致') # 把所有钩子数据都返回 return self.cleaned_data

 

 。

 【form组件源码】

 

 1 切入点
 2 
 3     form_obj.is_valid()
 4     
 5 源码:
 6     def is_valid(self):
 7         """Return True if the form has no errors, or False otherwise."""
 8         return self.is_bound and not self.errors
 9 
10 如果is_valid要返回True,那么self.is_bound要为True,且self.errors要为Flase
11 
12 
13 ----------------
14 is_bound
15 
16  def __init__(
17         self,
18         data=None,
19         files=None,
20         auto_id="id_%s",
21         prefix=None,
22         initial=None,
23         error_class=ErrorList,
24         label_suffix=None,
25         empty_permitted=False,
26         field_order=None,
27         use_required_attribute=None,
28         renderer=None,
29     ):
30         self.is_bound = data is not None or files is not None
31 其中data就是我们传进去的形参,只要传值了就为True
32 
33 
34 ---------------------------------
35 errors:默认为None
36 
37     @property
38     def errors(self):
39         """Return an ErrorDict for the data provided for the form."""
40         if self._errors is None:
41             self.full_clean()
42         return self._errors
43 
44 form组件所有的功能基本都出自于该方法
45 
46     def full_clean(self):
47         """
48         Clean all of self.data and populate self._errors and self.cleaned_data.
49         """
50         self._errors = ErrorDict()
51         if not self.is_bound:  # Stop further processing.
52             return
53         self.cleaned_data = {}
54         # If the form is permitted to be empty, and none of the form data has
55         # changed from the initial data, short circuit any validation.
56         if self.empty_permitted and not self.has_changed():
57             return
58 ****************************
59         self._clean_fields()   # 校验字段
60         self._clean_form()   # 全局钩子
61         self._post_clean()

 

 

 

 

 

 

 

 

posted on 2024-03-04 21:44  认真的六六  阅读(7)  评论(0编辑  收藏  举报