day06 form组件

day06 form组件

昨日内容复习

  • ajax实现二次确认

    #原生js
    	1.按钮绑定点击事件
        2.判断是否发送ajax请求
        	数据携带方式注意
    #进阶版 引用第三方插件sweetalert
    	1.给按钮绑定点击事件
        2.赋值插件代码
        3.修改部分内容
    #前后端交互使用ajax    那么后端推荐返回字典类型的json格式字符串
    
  • ajax发送文件数据

    先要获取input框用户上传的文件数据 如果获取多个数据 最后面的索引0不需要加
    # 其实$('#d1')[0]  ==转成原生js对象  
    	两种方式1.用jquery版本
        	$('#d1')[0].files[0]
         第二种方式使用js代码  
        	document.getElementById('d1').files[0]
    #js内置对象FormData
    	产生一个form对象
        对象.append('别名',获取数据的values)
        formDataObj.append('name',$('#d2').val())
        #发送文件需要额外配置的两个参数contentType,processData
        contentType: false,   #这块注意发送json格式数据要写成'application/json'相当于报头
        processData: false,
        data:formdata对象
    
    
  • datetype参数

    后端使用HttpResponse返回的json格式字符串 ,他会自动反序列化成js格式对应的数据类型
    后端使用JsonResponse返回的json格式字符串 ,他加不加都行
    语法格式:dataType:'JSON' 指定后 后端返回给前端的数据如果不是json格式的  他不会反序列化  会自动区分是不是json格式的
    # 以后推荐加上 增加程序兼容性
    
  • 序列化组件

    from django.core import serializers
     #serializers.serializer 直接可以把 queryset列表套数据对象 转换成json格式的列表套字典 字典里自动加来自于哪个应用下的那个表,主键值 ,表的字段用一个fields做一个字典嵌套  外键什么的也会放在一个字典里
        res=serializers.serialize('json',books_queryset) #books_queryset里面有很多很多数据对象
        return HttpResponse(res)
    
    序列化其实就是将数据组织成字典并序列化成json格式的过程
    from django.core import serializers
    
  • 批量插入(bulk_create)

    当需要频繁的插入大量数据的时候可以考虑是该方法 能够极大地提升效率
    #生成器表达式  生产一个new_obj_iter里面存放了好多好多对象对象里面存了 title这个属性
        new_obj_iter=(models.Book(title='第%s本书'%i) for i in range(100000))
        #批量插入bulk_create
        models.Book.objects.bulk_create(new_obj_iter)
    
    
  • 分页

    # queryset支持索引和切片[0,10] 索引0开始到10
    1.需要数据的总量
    2.需要定义每页展示多少条
    3.需要计算总共需要多少页
    4.需要推导出几个核心参数的数学关系
    5.需要后端生成html代码
    
    1.前端传给后端要看第几页数据 后端获取请求的页数
    2.后端定义页面显示多少数据 起始位置 终止位置 他们是有逻辑关系的
    3.后端通过divmod 获取总共多少页 有余数+1 
    4.后端定义 一个变量=当前页数 判断当前选择的页数小于最小页的中间位置  让这个变量=最小页的中间位置 为了防止左面越界 右面的也设置
    5.后端编写HTML代码 for循环 开始位置-5 结束为止+6  设置超链接 并且选择的列高亮显示
    6.前端接受数据 for循环数据对象 取title 加上一个分页器bootstrap 引用后面的html代码 实现显示十页
    
    
    

今日内容概要

form组件

是modelform组件的前身 功能更加强大 学完drf再学更容易接受

今日内容详细

form组件前言

low 版本校验
def myform(request):
    error_dict={'User_msg':'','Pwd_msg':''}
    if request.method=='POST':
        username= request.POST.get('username')
        password=request.POST.get('password')
        if username=='zhang':
            error_dict['User_msg']='名字不能是zhang'
        if len(password)==0:
            error_dict['Pwd_msg']='密码不能为空'
    return render(request,'myform.html',locals())
前端需要后面加一个span标签 里面引用后端的error_dict的里面的User_msg 或者Pwd_msg 实现了校验
自定义数据校验功能 主要步骤
    1.搭建前端页面				标签渲染
    2.校验数据是否合法			   数据校验
    3.返回相应的提示信息			  提示信息
form组件可以自动实现

day06 form组件

form组件基本定义

与models定义类基本一致
但是这里定义在views视图层
1.先导入
	from django import forms
2.定义
	class MyFormWow(forms.Form):
    #username字段最长8位,最短3位
    username=forms.CharField(max_length=8,min_length=3)
    # password字段最长8位,最短3位
    password=forms.CharField(min_length=3,max_length=8)
    # email字段必须符合邮箱格式 可以为空
    email=forms.EmailField(required=False))

form组件数据校验功能

 #导入模块
    from app01 import views
    #1传入待校验的数据
    obj=views.MyFormWow({'username':'zhang','password':'123','email':'123@q.com','hobby':'111'})
    #2.判断所有的数据是否合规
    print(obj.is_valid())   #结果为布尔值  (只有所有的数据都合规才返回True)
    #3.查看符合点击校验的数据
    print(obj.cleaned_data) #结果为字典 所有通过校验的数据
    #4.如何查看不符合条件校验的数据
    print(obj.errors)       #返回错误字段和错误原因
"""
1.在传递数据的时候 如果多传了额外字段 没有关系   form不校验 不理这个多传入的字段
2.form组件内部定义的字段数据 默认都是必填的
	可以通过修改参数required=False来控制是否必填  默认=True 必填
"""

form组件渲染标签功能

#从新添加一个urls 路由关系 my_form 里面创建一个myform对象 返回给前端界面
def my_form(request):
    obj=MyFormWow()
    return render(request,'my_form.html',locals())
"""
#自动渲染出在定义类时候 需要用户传的数据对应的标签 
自动渲染的标签文本名称默认采用字段名首字母大写的形式
	可以通过label参数自定义名称
form只渲染获取用户数据的标签 不渲染提交按钮 需要我们自己编写
"""

#前端界面  渲染标签方式1   封装程度高 不容易扩展 一般用于本地测试  
            {{ obj.as_p }}   #自动生成 字段名字后面跟个输入框
            {{ obj.as_ul }} #自动生成 无序 用ul里面的li包裹
            {{ obj.as_table }}	#自动生成 在一行
            
#渲染标签方式2 扩展性高 书写麻烦
'''
 obj.username.label:获取label值 
 obj.username.id_for_label:获取输入框的id值  这个实现了点前面这个label 光标跳到后面的输入框
 obj.username :该输入框
'''
    <div>
        <label for="{{ obj.username.id_for_label }}">{{ obj.username.label }}</label>
        {{ obj.username }}
        </div>
    <div>
        <label for="{{ obj.password.id_for_label }}">{{ obj.password.label }}</label>
         { obj.password }}
         </div>
     <div>
         <label for="{{ obj.email.id_for_label }}">{{ obj.email.label }}</label>
          {{ obj.email }}
      </div>

#渲染标签方式3   融合了方式1和方式2的优势(推荐使用) 书写简单 易扩展
 {% for foo in obj %}   #for循环一次就拿这个对象的类的字段一次 .参数的形式拿值
       <p>
          <label for="{{ foo.id_for_label }}">{{ foo.label }}</label>
          {{ foo }}
        </p>

{% endfor %}

form组件数据提示信息功能

#前端校验 可有可无
在form表单加上一个novalidate 意思是不让前端校验,让后端校验
	<form action="" method="post" novalidate>
#发过来的数据后端获取
def my_form(request):
    obj=MyFormWow()
    if request.method=='POST':  
        #直接将数据传入类中
        obj=MyFormWow(request.POST)
        #判断数据是否合规
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            print(obj.errors)
         #不管是post get请求最后都会返回   get请求返回的是一个空的obj ,post 返回的是有正常信息,错误信息的obj
    return render(request,'my_form.html',locals()) 

#错误信息前端也可以显示span标签 有值显示 没值不显示 不占空间  .0是让他只显示文本 
	<span style="color: red">{{ foo.errors.0 }}</span>

# 后端自定义提示信息 error_messages  在类定义时候使用  还有一种方式 settings字符编码里面LANGUAGE_CODE='zh-hans'  改成中文
 error_messages={
     'max_length':'用户名最多8位',
     'min_length':'用户名最少3位',
     'required':'用户名不能为空' #不能为空
 }
邮箱的错误有一点不一样
error_messages={
    'required': '邮箱不能为空',
    'invalid':'邮箱格式不正确'    #这个参数邮箱格式的
}

form组件进阶

数据校验--正则校验
#先导入模块
	from  django.core.validators import RegexValidator
定义一个新的字段
phone=forms.CharField(label='手机号',
                    validators=[RegexValidator(r'^[0-9]+$', '请输入数字'),
                    RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
                    ],
    )
#钩子函数 分为局部钩子 和全局钩子 前面基本校验规则执行之后才会执行钩子函数 顺序为 mix_length参数校验--validators正则校验--钩子函数
#局部钩子 钩一些数据  校验单子字段 校验用户名是否已存在 在定义类时候写好 写个方法
    def clean_username(self): #
        #1.获取用户名数据 在已经校验完的数据找
        username=self.cleaned_data.get('username')
        #2.校验用户名是否已存在
        if username=='zhang':
            #2.1存在添加用户名存在信息
            self.add_error('username','用户名已存在')
        #3.返回勾出来的数据
        return username
#全局钩子 校验第一次输入的密码和第二次输入的是否一致 名字只能交clean
    def clean(self):
        password=self.cleaned_data.get('password')
        confirm_password=self.cleaned_data.get('confirm_password')
        if not password==confirm_password:
            self.add_error('confirm_password','两次输入密码不一致')
        return self.cleaned_data  #全局数据返回

form组件

#参数部分
	label         字段名称
    required       是否必填 True必填  False非必填   默认True
    initial        默认值
    error_messages  自定义错误信息 
    widget           修改标签的属性 比如type class 等
    	widget=forms.widgets.PasswordInput() #修改type
        widget=forms.widgets.TextInput(attrs={'class':'form-control'}) #修改什么属性写什么用字典的形式
        
        
#一些不常用的
在使用选择标签时,需要注意choices的选项可以配置从数据库中获取,但是由于是静态字段 获取的值无法实时更新,需要重写构造方法从而实现choice实时更新。获取数据库的值给choise赋值
    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields


    class MyForm(Form):

        user = fields.ChoiceField(
            # choices=((1, '上海'), (2, '北京'),),
            initial=2,
            widget=widgets.Select
        )

        def __init__(self, *args, **kwargs):
            super(MyForm,self).__init__(*args, **kwargs)
            # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
            # 或
            self.fields['user'].choices = 		models.Classes.objects.all().values_list('id','caption')
#单选框
    gender = forms.fields.ChoiceField(
            choices=((1, "男"), (2, "女"), (3, "其他")),
            label="性别",
            initial=1,
            widget=forms.widgets.RadioSelect()
        )
#单选框radioSelect
    hobby = forms.ChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
            label="爱好",
            initial=3,
            widget=forms.widgets.Select()
        )	
#多选框Select
     hobby1 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.SelectMultiple()
        )

#单选checkbox
    keep = forms.ChoiceField(
            label="是否记住密码",
            initial="checked",
            widget=forms.widgets.CheckboxInput()
        )
#多选checkbox
    hobby2 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.CheckboxSelectMultiple()
        )
#这几个不常用的前端如图显示 

day06 form组件

form组件源码

"""阅读源码是提升编程思维的最佳方式!!!"""
突破口is_valid
上一篇:简洁的JS代码片段


下一篇:vue 页面与弹框组件之间的相互传值