Dango生命周期回顾与forms组件

Django请求生命周期

前后端数据交换

一般的编码格式

1、urlencoded
2、formdata
3、application/json

form表单编码格式

form表单默认的编码格式是urlencoded不支持发文件(只能把文件名发过去)
它所对应数据格式 username=jason&password=123

formdata

request.POST只能解析urlencoded数据格式的数据
formdata django会帮你把文件数据取出来 放入request.FILES里面 专门用来传文件的

.html
<form action="" method="post" enctype="multipart/form-data">  //注意enctype
    {% csrf_token %}
    username: <input type="text" name="username"><br>
    password: <input type="password" name="password"><br>
    img: <input type="file" name="myfile"><br>
    <input type="submit" value="提交">

</form>

view.py
file_obj = request.FILES.get('myfile')
        print(file_obj.name)  # 查看当前文件对象的文件名
        with open(file_obj.name,'wb') as f:
            for line in file_obj:
                f.write(line)

AJAX

Ajax默认提交的编码格式也是urlencoded
当用ajax传输json格式的数据时候 django不会做任何处理
数据以二进制形式放在request.body中 你可以手动解码加反序列化拿到对应的字典格式数据

bytes_str = request.body
        res = json.loads(bytes_str.decode('utf-8'))
        print(res,type(res))

jax发送文件 利用js内置的FormData对象

<input type="file" name="myfile" id="d2">
<button id="d1">点我</button>

$('#d1').click(function () {
        // 如果用ajax发送文件 需要使用内置对象FormData
        var formData = new FormData();  // 生成一个内置对象
        // 内置对象formdata既可以传普通的键值对,也可以传文件
        formData.append('name','jason');  // 普通键值对
        formData.append('password','123');
        // 传文件
        var fileObj = $('#d2')[0].files[0];  // 先获取标签对象 转成原生js对象 通过内置的files方法拿到所有的文件对象列表 然后去索引0拿到文件对象
        formData.append('myfile',fileObj);
        $.ajax({
            url:'',  // 不写默认朝当前页面所在的url地址提交
            type:'post',
            // 注意ajax在发送文件的时候 需要你手动指定两个特殊的参数,这两个必须写
            contentType:false,  // 不要用任何编码 使用我formdata自带的编码即可
            processData:false,  // 浏览器不要处理我的数据 是什么就什么
            data:formData,
            success:function (data) {
                alert(data)
            }

        })
    })

forms组件

forms组件的3个过程

1.前端渲染展示页面 获取用户输入 >>> 渲染页面
2.将数据发送给后端进行数据的合法性校验 >>> 数据校验
3.将不合法的提示信息展示给用户看 >>> 展示提示信息
关于数据的校验
1.前端
2.后端
数据的校验前端可以没有,但是后端一定要做!!!

自己写一个前后端校验的例子

.html
<form action="" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    username: <input type="text" name="username">
    <span>{{ back_dic.flag }}</span>
    <br>
    password: <input type="password" name="password">
    <span>{{ back_dic.msg }}</span>
    <br>
    img: <input type="file" name="myfile"><br>
    <input type="submit" value="提交">
</form>

views.py
def index(request):
    if request.method == 'POST':
        # file_obj = request.FILES.get('myfile')
        # print(file_obj.name)
        # print(request.body)
        back_dic = {"flag":'',"msg":''}
        username = request.POST.get('username')
        password = request.POST.get('password')
        if not username:
            back_dic['flag'] = "账户不能为空"
        if len(password) < 6:
            back_dic['msg'] = "密码太短"
    return render(request,"inddex.html",locals()) //将函数内的名称空间全部传过去

forms组件校验数据

1.校验数据

forms组件的校验数据的使用
1.定义一个继承forms.Form一个类
from django import forms
class MyForm(forms.Form):
	username = forms.CharField(max_length=6)  # username最长只能是6位
	password = forms.CharField(max_length=8,min_length=3)  # password最长8位 最短3位
	email = forms.EmailField()  # email接受的数据必须符合邮箱格式
完整版
# 使用forms组件第一步需要你手动写一个类 并且要继承forms.Form
from django import forms
from django.forms import widgets   # 当你用forms点widgets点不出来的时候 自己手动导入一下
from django.core.validators import RegexValidator
class MyForm(forms.Form):
    username = forms.CharField(max_length=6,label='用户名',initial='我是最帅的',error_messages={
                                                                'max_length':'用户名最长6位',
                                                                'required':'用户名不能为空'

    })  # username最长只能是6位
    password = forms.CharField(max_length=8,min_length=3,label='密码',
                               widget=widgets.PasswordInput(attrs={'class':'form-control c1',})

                               )  # password最长8位 最短3位
    confirm_password = forms.CharField(max_length=8, min_length=3, label='确认密码',
                               widget=widgets.PasswordInput(attrs={'class': 'form-control c1', })

                               )  # password最长8位 最短3位
    phone = forms.CharField( validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],)
    email = forms.EmailField(label='邮箱',error_messages={
                                            'required':'邮箱不能为空',
                                            'invalid':'邮箱格式不正确'
    })  # email接受的数据必须符合邮箱格式

    forms组件中所有的字段默认都是必填的(不能为空)
    在数据都满足forms组件校验规则的情况下 多传的数据不校验 没有关系
    


    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )
    hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )

    hobby1 = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )
2.给forms组件传参数 (字典的显示)
	obj = views.MyForm({'username':'egondsb','password':'12','email':'123@qq.com'})
3.查看数据是否完全合法
	obj.is_valid()
4.查看所有校验通过的数据
	obj.cleaned_data
	{'email': '123@qq.com'}
5.查看所有没有通过的数据
	obj.errors
	"""
	{
	'username': ['Ensure this value has at most 6 characters (it has 7).'], 
	'password': ['Ensure this value has at least 3 characters (it has 2).']}
	"""

2.渲染标签

forms组件只能帮你渲染 获取用户输入(输入框 选择框 下拉框...)的标签
提交按钮也得自己写
form表单取消前端校验功能

	<form action="" method="post" novalidate>	

forms组件当前端输入的信息不合法的时候 页面上的数据保留不会刷新 这样方便用户修改

3.展示提示信息

	{% for foo in form_obj %}
        <p>
        {{ foo.label }}{{ foo }}
         <span>{{ foo.errors.0 }}</span>
         </p>
	{% endfor %}

forms组件的钩子函数

# 局部钩子
def clean_username(self):
# 用户名中不能有666
	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')
	confirm_password = self.cleaned_data.get('confirm_password')
	if not password == confirm_password:
		self.add_error('confirm_password','两次密码不一致')
	return self.cleaned_data

django代码测试

import os
import sys

if __name__ == "__main__":
	os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day66.settings")
	import django
	django.setup()
		  
	from app01 import models
	print(models.Userinfo.objects.all())
posted @ 2019-07-22 15:18  Huanghongzheng  阅读(231)  评论(0编辑  收藏  举报