首页 > 代码库 > Django(三)

Django(三)

一、Form表单

 

在实际的生产环境中比如登录和验证的时候,我们一般都使用Jquery+ajax来判断用户的输入是否为空,假如JS被禁用的话,咱们这个认证屏障是不是就消失了呢?(虽然一般不会禁用掉但是还是存在风险)所以我们一般做两种认证一种是前端做一遍认证,在后端做一遍认证。

如果前端中要涉及到很多input,提交到后台,后台要一一取出,分别做验证,这是件很痛苦的事。

 
def register(request):    if request.method == "POST":        ret = {"status":False,"msg":""}        u = request.POST.get(‘user‘,None)        e = request.POST.get(‘email‘,None)        p = request.POST.get(‘password‘,None)        p2 = request.POST.get(‘password2‘,None)        #这里有个问题,如果,这个from表单有20个input,你在这里是不是的取20次?        count = models.UserInfo.objects.filter(user=u).count()        if count == 0:            if p == p2:                print("注册成功")                models.UserInfo.objects.create(user=u, email=e, password=p)                data_list = models.UserInfo.objects.all()                ret["status"] = True                ret["msg"] = "注册成功,请登录"                return  HttpResponse(json.dumps(ret))                # return redirect(‘/index/‘)            else:                print(‘diff‘)                ret["msg"] = "两次输入密码不一致"                return HttpResponse(json.dumps(ret))        elif len(u) > 0 and count >= 1:            print(‘用户名已经存在‘ )            ret["msg"] = "用户名已经存在"            return HttpResponse(json.dumps(ret))        else:            return render( request, ‘cmdb/register.html‘, )        #验证:    #输入不能为空,并且有的可以为空有的不可以为空    #如果email = xxxx 这样合法吗    ‘‘‘    你在这里是不是需要做一大堆的输入验证啊?并且有很多这种页面会存在这种情况,如果每个函数都这样做估计就累死了    ‘‘‘    if request.method == ‘GET‘:        return render( request, ‘cmdb/register.html‘, )    
 

在样能解决这个问题呢?通过Django的form来实现,其他语言也有叫做(模型绑定)

Django的form的作用:

1、生成html标签

2、用来做用户提交的验证

1、生成html标签

views

 
from django import formsclass LoginForm(forms.Form):    user = forms.CharField(required=True, error_messages={‘required‘: ‘用户名不能为空.‘})    pwd = forms.CharField(required=True,                          min_length=6,                          max_length=10,                          error_messages={‘required‘: ‘密码不能为空.‘, ‘min_length‘: "至少6位"})    num = forms.IntegerField(error_messages={‘required‘: ‘数字不能空.‘,‘invalid‘: ‘必须输入数字‘})    phone = forms.CharField(validators=[mobile_validate, ],)    test = forms.CharField(widget=forms.Textarea(attrs={‘class‘: ‘c1‘}))def login(request):    if request.POST:        objPost = LoginForm(request.POST)        ret = objPost.is_valid()        # print(objPost)        print(ret)        if ret:            print(objPost.clean())        else:            from django.forms.utils import ErrorDict            #print(type(obj.errors),obj.errors.as_json())            # obj1.errors            print(objPost.errors.as_json())        return render(request, ‘login.html‘,{‘obj1‘: objPost})    else:        objGet = LoginForm()        return render(request, ‘login.html‘,{‘obj1‘: objGet})
 

 

html

 
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .error-msg{            color: red;        }    </style></head></head><body>    <form action="/app01/login/" method="POST">        <div>            <div>                {{ obj1.user }}                {% if obj1.errors.user %}                    <span class="error-msg">{{ obj1.errors.user.0 }}</span>                {% endif %}            </div>            <div>                {{ obj1.pwd }}                    <span class="error-msg">{{ obj1.errors.pwd.0 }}</span>            </div>            <div>                {{ obj1.num }}                    <span class="error-msg">{{ obj1.errors.num.0 }}</span>            </div>            <div>                {{ obj1.phone }}                    <span class="error-msg">{{ obj1.errors.phone.0 }}</span>            </div>            <div>                {{ obj1.test }}                <span class="error-msg">{{ obj1.errors.test.0 }}</span>            </div>            <input type="submit" value="http://www.mamicode.com/提交">        </div>    </form></body></html>
 

技术分享

 2、简单的form表单验证用户输入的内容

 
def login(request):    if request.POST:        #获取用户输入一句话就搞定        objPost = LoginForm(request.POST)        ‘‘‘        咱们把post过来的数据当参数传给LoginForm咱们定义的这个类,LoginForm会自动会去你提交的数据        user/pwd/num/phone 自动的封装到objPost里,封装到这个对象里我们就可以判断输入是否合法        ‘‘‘        ret = objPost.is_valid()        # print(objPost)        print(ret)        if ret:            print(objPost.clean())        else:            from django.forms.utils import ErrorDict            #print(type(obj.errors),obj.errors.as_json())            # obj1.errors            print(objPost.errors.as_json())        return render(request, ‘login.html‘,{‘obj1‘: objPost})#然后把对象传给html    else:        objGet = LoginForm() #创建了这个对象        return render(request, ‘login.html‘,{‘obj1‘: objGet})from django.views.decorators.csrf import csrf_exempt,csrf_protect
 

 

当我们输入不合法的时候,(在创建类设置的需求)为空、或者不是email格式的时候!

技术分享

这样在后端我们是不是就有一套验证的机制?就可以通过is_valid()来判断用户输入是否合法!如果不合法就把返回信息发送过去,如果合法获取数据操作即可!

捕获错误信息并返回

 
from django import formsclass LoginForm(forms.Form):    user = forms.CharField(required=True, error_messages={‘required‘: ‘用户名不能为空.‘})    pwd = forms.CharField(required=True,                          min_length=6,                          max_length=10,                          error_messages={‘required‘: ‘密码不能为空.‘, ‘min_length‘: "至少6位"})    num = forms.IntegerField(error_messages={‘required‘: ‘数字不能空.‘,‘invalid‘: ‘必须输入数字‘})    phone = forms.CharField(validators=[mobile_validate, ],)    test = forms.CharField(widget=forms.Textarea(attrs={‘class‘: ‘c1‘}))
def login(request):
if request.POST:
#获取用户输入一句话就搞定
objPost = LoginForm(request.POST)
‘‘‘
咱们把post过来的数据当参数传给LoginForm咱们定义的这个类,LoginForm会自动会去你提交的数据
user/pwd/num/phone 自动的封装到objPost里,封装到这个对象里我们就可以判断输入是否合法
‘‘‘
ret = objPost.is_valid()
# print(objPost)
print(ret)
if ret:
print(objPost.clean())
#通过验证,获取提交的数据
‘‘‘
{‘user‘: ‘asfd‘, ‘num‘: 1, ‘pwd‘: ‘dsafss‘, ‘test‘: ‘32‘, ‘phone‘: ‘13331525685‘}
‘‘‘
else:
from django.forms.utils import ErrorDict
#print(type(obj.errors),obj.errors.as_json())
# obj1.errors
print(objPost.errors)
‘‘‘
<ul class="errorlist"><li>phone<ul class="errorlist"><li>手机号码格式错误</li></ul></li></ul>
‘‘‘
return render(request, ‘login.html‘,{‘obj1‘: objPost})#然后把对象传给html,在把错误信息传递过去
else:
objGet = LoginForm() #创建了这个对象
return render(request, ‘login.html‘,{‘obj1‘: objGet})#然后把对象传给html
 
 

html标签,使用 login 中定义的obj1 对应的errors输出

 
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .error-msg{            color: red;        }    </style></head></head><body>    <form action="/app01/login/" method="POST">        <div>            <div>                {{ obj1.user }}                {% if obj1.errors.user %}                    <span class="error-msg">{{ obj1.errors.user.0 }}</span>                {% endif %}            </div>            <div>                {{ obj1.pwd }}                    <span class="error-msg">{{ obj1.errors.pwd.0 }}</span>            </div>            <div>                {{ obj1.num }}                    <span class="error-msg">{{ obj1.errors.num.0 }}</span>            </div>            <div>                {{ obj1.phone }}                    <span class="error-msg">{{ obj1.errors.phone.0 }}</span>            </div>            <div>                {{ obj1.test }}                <span class="error-msg">{{ obj1.errors.test.0 }}</span>            </div>            <input type="submit" value="http://www.mamicode.com/提交">        </div>    </form></body></html>
 

这样如果,我都按照要求提交,就可以取到数据了?这样咱们就不用自己去拿数据是

1
{‘user‘: ‘asfd‘, ‘num‘: 1, ‘pwd‘: ‘dsafss‘, ‘test‘: ‘32‘, ‘phone‘: ‘13331525685‘}

 3、form表单定制化

3.1、自定义报错内容

在form里有一个参数:error_messages  在他这里就可以定义报错内容

 
class UserInfo(forms.Form):     email = forms.EmailField(required=True,error_messages={‘required‘:u‘邮箱不能为空‘}) #required是否可以为空,如果为False说明可以为空     host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘}) #如果required不写默认为Ture     port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})     mobile = forms.CharField(error_messages={‘required‘:u‘手机不能为空‘},                              widget=forms.TextInput(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘手机号码‘})#给input添加属性                                    #这里默认是TextInput,标签                              )

效果:

技术分享

3.2给userinfo增加一个备注

 
class UserInfo(forms.Form):     email = forms.EmailField(required=True,error_messages={‘required‘:u‘邮箱不能为空‘}) #required是否可以为空,如果为False说明可以为空     host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘}) #如果required不写默认为Ture     port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})     #默认mobile里有一个默认为空的机制,我们在原有的参数里增加怎们自定义的方法     mobile = forms.CharField(validators=[mobile_validate,],#应用咱们自己定义的规则                              error_messages={‘required‘:u‘手机不能为空‘},                              widget=forms.TextInput(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘手机号码‘})                                    #这里默认是TextInput,标签                              )     #咱们在新增一个备注     memo = forms.CharField(required=False,                            widget=forms.Textarea(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘备注‘})     )
 

效果如下:

技术分享

3.3 生成select标签

 
class UserInfo(forms.Form):     email = forms.EmailField(required=True,error_messages={‘required‘:u‘邮箱不能为空‘}) #required是否可以为空,如果为False说明可以为空     host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘}) #如果required不写默认为Ture     port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})     #默认mobile里有一个默认为空的机制,我们在原有的参数里增加怎们自定义的方法     mobile = forms.CharField(validators=[mobile_validate,],#应用咱们自己定义的规则                              error_messages={‘required‘:u‘手机不能为空‘},                              widget=forms.TextInput(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘手机号码‘})                                    #这里默认是TextInput,标签                              )     #咱们在新增一个备注     memo = forms.CharField(required=False,                            widget=forms.Textarea(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘备注‘})     )     user_type_choice = (        (0, u‘普通用户‘),        (1, u‘高级用户‘),)         user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={‘class‘:‘form-control‘}))
 

 

技术分享

3.4、关于后端验证

这个后端验证是必须要有验证机制的,前端可以不写但是后端必须要写!前端的JS是可以被禁用掉到。

3.5 Django 优化错误信息显示

设置显示error的样式

error_msg = user_input_obj.errors.as_data()#这里原来什么都没写,默认是ul的样式,默认是as_ul(),如果我们写成as_data()返回的就是一个原生的字符串            #还有一个as_json

 

实例:

 
import refrom django import formsfrom django.core.exceptions import ValidationError#自定义方法def mobile_validate(value):    mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘) #正则匹配    if not mobile_re.match(value):        raise ValidationError(‘手机号码格式错误‘) #如果没有匹配到主动出发一个错误class UserInfo(forms.Form):    user_type_choice = (        (0, u‘普通用户‘),        (1, u‘高级用户‘),)    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={‘class‘:‘form-control‘}))    email = forms.EmailField(required=True,error_messages={‘required‘:u‘邮箱不能为空‘}) #required是否可以为空,如果为False说明可以为空    host = forms.CharField(error_messages={‘required‘:u‘主机不能为空‘}) #如果required不写默认为Ture    port = forms.CharField(error_messages={‘required‘:u‘端口不能为空‘})    #默认mobile里有一个默认为空的机制,我们在原有的参数里增加怎们自定义的方法    mobile = forms.CharField(validators=[mobile_validate,],#应用咱们自己定义的规则                              error_messages={‘required‘:u‘手机不能为空‘},                              widget=forms.TextInput(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘手机号码‘})                                    #这里默认是TextInput,标签                              )    #咱们在新增一个备注    memo = forms.CharField(required=False,                            widget=forms.Textarea(attrs={‘class‘:‘form-control‘,‘placeholder‘:u‘备注‘}))
def user_list(request):
obj = UserInfo() #创建了这个对象
if request.method == ‘POST‘:
#获取用户输入一句话就搞定
user_input_obj = UserInfo(request.POST)

if user_input_obj.is_valid(): #判断用户输入是否合法
data = http://www.mamicode.com/user_input_obj.clean() #获取用户输入
print(data)
else:
#如果发生错误,捕捉错误
error_msg = user_input_obj.errors.as_data()#这里原来什么都没写,默认是ul的样式,默认是as_ul(),如果我们写成as_data()返回的就是一个原生的字符串
#还有一个as_json

print(error_msg) #打印一下然后看下他的类型
#然后把错误信息返回
return render(request,‘user_list.html‘,{‘obj‘:obj,‘errors‘:error_msg,})#然后把对象传给html,在把错误信息传递过去
return render(request,‘user_list.html‘,{‘obj‘:obj,})#然后把对象传给html
 
 

 

html

 
{% load mytag %}<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Shuai</title></head><body>    <form action="/app01/user_list/" method="post">        <p>用户类型:{{ obj.user_type }}<span>{% error_message errors.user_type %}</span></p>        <p>主机:{{ obj.host }}<span>{%  errors.host %}</span></p>        <p>端口:{{ obj.port }}<span>{% error_message errors.port %}</span></p>        <p>邮箱:{{ obj.email }}<span>{% error_message errors.email %}</span></p>        <p>手机:{{ obj.mobile }}<span>{% error_message errors.mobile %}</span></p>        <p>备注:{{ obj.memo }}<span>{% error_message errors.memo %}</span></p>        <input type="submit" value="http://www.mamicode.com/submit"/>    </form></body></html> 
 

 

 

 

 

二、CSRF 跨站请求

 

viwes.py

from django.views.decorators.csrf import csrf_exempt,csrf_protect@csrf_exemptdef csrf(request):    return render(request,csrf.html)

 

csrf.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title></title></head><body>        <form action="/csrf/" method="post">            {% csrf_token %}            <input type="text" name="v" />            <input type="submit" value=http://www.mamicode.com/"提交" />        </form>        <input type="button"  value=http://www.mamicode.com/"Ajax提交" onclick="DoAjax();" />        <script src=http://www.mamicode.com/"/static/jquery-2.1.4.min.js"></script>        <script src=http://www.mamicode.com/"/static/jquery.cookie.js"></script>    <script>        // 去cookie中获取值        var csrftoken = $.cookie(csrftoken);        function csrfSafeMethod(method) {            // these HTTP methods do not require CSRF protection            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));        }        $.ajaxSetup({                                                           #用于ajax请求绑定cookie            beforeSend: function(xhr, settings) {                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {                    xhr.setRequestHeader("X-CSRFToken", csrftoken);                }            }        });        function DoAjax(){            $.ajax({                url: /csrf/,                type: POST,                data: {k1: v1},                success: function (data) {                    console.log(data);                }            })        }    </script></body></html>

 

 

三、cookie 

 1.cookie设置

viwes.py

def cookie(request):    print(request.COOKIES)    obj = render(request, cookie.html)    obj.set_cookie(k3,v3,path=/cookie/)                    #浏览器设置cookie    return obj

 

 

技术分享

 

 

技术分享

 

 

 

2.cookie登陆(cookie内容可以串改,登陆不使用cookie登陆,cookie一般保存不敏感的信息)

viwes.py 

def log(request):    if request.method == POST:        u = request.POST.get(user)        p = request.POST.get(pwd)        if u == alex and p == 123:            print(u)            red = redirect(/index/)            red.set_cookie(username, u)            return red        else:            return render(request, log.html)    else:        return render(request, log.html)

 

 

log.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title></title></head><body>    <form action="/log/"  method="POST">        <input type="text" name="user">        <input type="text" name="pwd">        <input type="submit" value=http://www.mamicode.com/"提交" />    </form></body></html>

 

 

四、session登陆

viwes.py

USER_LIST = [alex,eric,wangminglong, hu]def session_login(request):    if request.method == POST:        u = request.POST.get(user)        p = request.POST.get(pwd)        if p == 123 and u in USER_LIST:            request.session[user] = u            return redirect(/session_index/)    return render(request,session_login.html)"""def session_index(request):    user = request.session.get(‘user‘,None)    if not user:        return redirect(‘/session_login/‘)    else:        return render(request,‘session_index.html‘,{‘user‘: user})"""def auth(func):    def inner(request, *args,**kwargs):        # print(request,args,kwargs)        user = request.session.get(user, None)        print(user)        if not user:            return redirect(/session_login/)        return func(request, *args,**kwargs)    return inner@authdef session_index(request):    user = request.session.get(user, None)    return render(request,session_index.html,{user: user})@authdef session_logout(request):    del request.session[user]    return redirect(/session_login/)

 

session_login.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title></title></head><body>    <h1>欢迎:{{ user }}登录</h1>    <a href=http://www.mamicode.com/"/session_logout/">注销</a></body></html>

 

session_index.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title></title></head><body>    <form action="/session_login/"  method="POST">        <input type="text" name="user">        <input type="text" name="pwd">        <input type="submit" value=http://www.mamicode.com/"提交" />    </form></body></html>

 

 

显示 登陆成功后

技术分享

 数据自动实现 

技术分享

 

Django(三)