python运维开发(十九)----Django后台表单验证、session、cookie、model操作

时间:2024-03-29 11:36:20

内容目录:

  • Django后台表单验证
  • CSRF加密传输
  • session、cookie
  • model数据库操作

Django后台Form表单验证

Django中Form一般有2种功能:

1、用于做用户提交数据的验证

from django import forms
class LoginForm(forms.Form):

基本验证demo

from django.shortcuts import render,HttpResponse
from django import forms
import json

# Create your views here.
class LoginForm(forms.Form):
    user = forms.CharField(required=True)
    pwd = forms.CharField(required=True)

def login(request):
    if request.method == 'POST':
        resault = {'status':False,'message':None}
        obj = LoginForm(request.POST)
        ret = obj.is_valid() #做Form的验证,如果填写正确返回为true否则返回false
        if ret:
            print(obj.clean())#正确时返回正确的值
            resault['status'] = True
        else:
            # print(type(obj.errors))#2通过Form方式来提交验证,错误时候打印错误信息类型,可以找到,
            # 通过错误类型导入ErrorDict模块,通过查看帮助信息,as_json方法,默认为as_ul方法
            from django.forms.utils import  ErrorDict
            print(obj.errors.as_json())
            error_str = obj.errors.as_json()
            resault['message'] = json.loads(error_str)#这里由于上面的是一个字典格式需要先转换为字符串方式loads一下
            # return HttpResponse(error_str)#测试时候返回错误信息
            return HttpResponse(json.dumps(resault))
        # u = request.POST.get('user')#1正常情况ajax提交请求验证
        # p = request.POST.get('pwd')
        # print(u,p)
    return render(request,'login.html')

view--demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .error_msg{
            color: red;
        }
    </style>
</head>
<body>

<div>
    <div>
        <p>用户名:<input type="text" name="user"/></p>

    </div>
    <div>
        <p>密 码 :<input type="password" name="pwd"/></p>
    </div>
    <input type="button" value="提交" onclick="DoSubmit();" />
</div>
<script src="/static/jquery-1.8.2.min.js"></script>
<script>
function DoSubmit() {
    var input_dict = {};
    $('input').each(function () {
        var v = $(this).val();
        var n = $(this).attr('name');
        input_dict[n] = v;
    });
    console.log(input_dict);
    $('.error_msg').remove();
    $.ajax({
        url:'/login/',
        type:'POST',
        data:input_dict,
        dataType:'json',//默认返回过来的值为str字符串,可以通过转换为json,打印data为一个对象
        success:function (resault) {
{#            console.log(data);#}//打印data的值
            if (resault.status){
                location.href = '/index/'
            }else {
            $.each(resault.message,function (k,v) {//json方式转换为对象格式所以循环这个对象,因为这个对象为字典方式所以定义k和v
{#                console.log(k,v);#}
                console.log(k,v[0].message);//打印input的name和错误信息
{#                <span class="error_msg">错误信息</span>#}
                //将错误信息添加一个span标签到input后面
                var tag = document.createElement('span');
                tag.className = 'error_msg';
                tag.innerText = v[0].message;
                //input[name="user"]
                $('input[name="' +k +'"]').after(tag)
            })}
        }
    })
}

</script>

</body>
</html>

login.html

上面的提示中都是英文我们可以自定义自己的报错中文提示方式

只需要更改上面的views代码中LoginForm的类

class LoginForm(forms.Form):
    user = forms.CharField(required=True,error_messages={'required':'用户名不能为空'})#中文提示
    pwd = forms.CharField(required=True,
                          min_length=6,#最小长度为6
#(默认提示Ensure this value has at least 6 characters (it has 3).)
                          max_length=10,
                          error_messages={'required': '密码不能为空',
                                          'min_length':'最少6位',
                                          'max_length':'最多10位'}
                          )

上面的中我们使用的只是CharField字符类型,在实际的环境中我们可能会遇到数字的验证IntegerField

例如我们在上面的demo中添加一个num的文本框做数字的验证

    #required 默认为True,不填写该参数时候是treu
    num = forms.IntegerField(error_messages={'required': '数字不能为空',
                                             'invalid':'输入的必须为数字',
                                             })

前端在密码后面添加上num的input文本框

    <div>
        <p>数 字 :<input type="text" name="num"/></p>
    </div>

效果展示

python运维开发(十九)----Django后台表单验证、session、cookie、model操作

除了上面的两种类型外还有其他的我们常用的类型验证

CharField 字符类型验证
IntegerField 数字类型验证
URLField URL验证
EmailField 邮箱小地址验证

如果django不能满足我们需要的验证的话,我们还可以自定义的数字验证

from 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 LoginForm(forms.Form):
    phone = forms.CharField(validators=[mobile_validate,],)

效果展示

python运维开发(十九)----Django后台表单验证、session、cookie、model操作

2、用于做用户提交数据的验证 + 生成HTML标签

from django.shortcuts import render,HttpResponse
from django import forms
import json,re
from 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('手机号码格式错误')

# Create your views here.
class LoginForm(forms.Form):
    user = forms.CharField(required=True,error_messages={'required':'用户名不能为空'})#中文提示
    pwd = forms.CharField(required=True,
                          min_length=6,#最小长度为6(默认提示Ensure this value has at least 6 characters (it has 3).)
                          max_length=10,
                          error_messages={'required': '密码不能为空',
                                          'min_length':'最少6位',
                                          'max_length':'最多10位'}
                          )
    #required 默认为True,不填写该参数时候是treu
    num = forms.IntegerField(error_messages={'required': '数字不能为空',
                                             'invalid':'输入的必须为数字',
                                             })
    phone = forms.CharField(validators=[mobile_validate,],)

def login(request):
    if request.POST:
        objPost = LoginForm(request.POST)
        ret = objPost.is_valid()  # 做Form的验证,如果填写正确返回为true否则返回false
        if ret:
            print(objPost.clean())  # 正确时返回正确的值
        else:
            from django.forms.utils import ErrorDict
            error_str = objPost.errors.as_json()
            # for k,v in objPost.errors.items():
            #     print(k,v)
            # print(objPost.errors['user'][0])
            # print(objPost.errors['pwd'][0])
            # print(objPost.errors['num'][0])
            # print(objPost.errors['phone'][0])
            pass
        return render(request,'login.html',{'obj1':objPost})
    else:
        objGet = LoginForm()
        return render(request,'login.html',{'obj1':objGet})

views-demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .error_msg{
            color: red;
        }
    </style>
</head>
<body>
<form action="/login/" method="POST">
    <div>
        <div>
             <p>用户名:{{ obj1.user }}
                 {% if obj1.errors.user  %}
                    <span class="error_msg">{{ obj1.errors.user.0 }}</span>
                 {% endif %}
             </p>

        </div>
        <div>
            <p>密 码 :{{ obj1.pwd }}
                {% if obj1.errors.pwd  %}
                    <span class="error_msg">{{ obj1.errors.pwd.0 }}</span>
                {% endif %}
            </p>
        </div>
        <div>
             <p>数 字 :{{ obj1.num }}
                 {% if obj1.errors.num  %}
                    <span class="error_msg">{{ obj1.errors.num.0 }}</span>
                 {% endif %}
             </p>
        </div>
        <div>
            <p>手 机 :{{ obj1.phone }}
                {% if obj1.errors.phone  %}
                    <span class="error_msg">{{ obj1.errors.phone.0 }}</span>
                {% endif %}
            </p>

        </div>
        <input type="submit" value="提交" />
    </div>
</form>
</body>
</html>

HTML-前端代码

通过后端来生成后端标签时候我们还可以定义自己的属性

    # test = forms.CharField(widget=forms.Textarea(attrs={'name': 'test'}))
    test_choices = (
        (0, '上海'),
        (1, '背景'),
    )
    test = forms.IntegerField(widget=forms.Select(choices=test_choices))

html代码

        <div>
            <p>测  试 :{{ obj1.test }}
                {% if obj1.errors.test  %}
                    <span class="error_msg">{{ obj1.errors.test.0 }}</span>
                {% endif %}
            </p>
        </div>

CSRF跨站请求伪造

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:
  中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

1、普通表单提交应用

#setting中配置
MIDDLEWARE_CLASSES = [
'django.middleware.csrf.CsrfViewMiddleware',
]
#urls配置
    url(r'^csrf/', views.csrf),

#views配置
def csrf(request):
    return render(request,'csrf.html')

#前端添加导入csrf_token配置
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/csrf/" method="post">
    {% csrf_token %}
    <input type="text" name="v"/>
    <input type="submit" value="form提交" />
</form>
    <input type="button" value="Ajax提交" onclick="DoAjax();" />
</body>
</html>

打开网页后调试模式我们能看到提交过来的一个字符串

python运维开发(十九)----Django后台表单验证、session、cookie、model操作

2、Ajax提交应用

js脚本

<script>
    var csrftoken = $.cookie('csrftoken');//从cookie获取值
    function csrfMethod(method) {
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    //所有ajax发送请求之前执行该ajaxSetup配置
    $.ajaxSetup({
        beforeSend:function (xhr,settings) {
            if (!csrfMethod(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>

cookie、Session缓存

一、cookie

Cookie是保存在客户端浏览器上的一个容器

1、获取cookie

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    参数:
        default: 默认值
           salt: 加密盐
        max_age: 后台控制过期时间

2、设置cookie

rep = HttpResponse(...) 或 rep = render(request, ...)

rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        key,              键
        value='',         值
        max_age=None,     超时时间
        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
        domain=None,      Cookie生效的域名
        secure=False,     https传输
        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });

二、Session

一般Session依赖于cookie,Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

1、数据库Session

Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)

b. 使用

    def index(request):
        # 获取、设置、删除Session中数据
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在则不设置
        del request.session['k1']

        # 所有 键、值、键值对
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()

        # 用户session的随机字符串
        request.session.session_key

        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()

        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")

        # 删除当前用户的所有Session数据
        request.session.delete("session_key")

数据库session

2、缓存Session

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存

b. 使用

    同上

Session缓存

3、文件Session

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T

    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存

b. 使用

    同上

文件session

4、缓存+数据库Session

数据库用于做持久化,缓存用于提高效率

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

b. 使用

    同上

缓存+数据库

5、加密cookie Session

a. 配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

b. 使用

    同上

Session+cookie

models数据库操作

基本操作

进阶

双下划线

  __ 大小于操作

__ 可以跨表

查询

1、一对多,查询所有用户类型等于 普通用户 的所有用户名和密码

2、三张表跨表操作

3、多对多

  创建

  操作_set