• Python学习笔记整理总结【Django】:模板语言、分页、Cookie、Session


    一、模板语言 

    1、在前段展示:对象/字典/元组

    class Business(models.Model):
        # id   #用默认的自增id列    即:Business中有3列数据(id, caption, code)
        caption = models.CharField(max_length=32)
        code = models.CharField(max_length=32,default="SA")
    #models.py
    from django.shortcuts import render,HttpResponse,redirect
    from app01 import models
    # Create your views here.
    def business(request):
        # 以下得到的都是QuerySet类型数据(类似于列表)
        v1 = models.Business.objects.all()                                # ①得到的是business obj对象  [obj(id,caption,code),obj(id,caption,code), ]
        v2 = models.Business.objects.all().values('id','caption')       # ②得到的是字典              [{'id':1,'caption': '运维部'},{'id':1,'caption': '运维部'},...]
        v3 = models.Business.objects.all().values_list('id','caption')  # ③得到的是元组              [(1,运维部),(2,开发)]
        return render(request, 'business.html', {'v1': v1,'v2': v2, 'v3': v3})
                                                                        #前端的三种形式:
                                                                            # {% for row in v %}
                                                                            #     ① <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li>
                                                                            #     ② <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li>
                                                                            #     ③ <li>{{ row.0 }} - {{ row.1 }} - {{ row.1 }</li>
                                                                            # {% endfor %}
    #views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>业务线列表(对象)</h1>
        <ul>
            {% for row in v1 %}
                <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li>
            {% endfor %}
        </ul>
        <h1>业务线列表(字典)</h1>
        <ul>
            {% for row in v2 %}
                <li>{{ row.id }} - {{ row.caption }}</li>
            {% endfor %}
        </ul>
        <h1>业务线列表(元组)</h1>
        <ul>
            {% for row in v3 %}
                <li>{{ row.0 }} - {{ row.1 }}</li>
            {% endfor %}
        </ul>
    </body>
    </html>
    #business.html
    from django.conf.urls import url
    from django.contrib import admin
    
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^business$', views.business), #加上终止符($)防止business匹配完成后以下的business_add不再执行
    ]
    #urls.py
    INSTALLED_APPS = [
                        'app01',
                    ]
    #settings.py

    2、排序
    ① forloop.counter 表示循环的次数,它从1开始计数,第一次循环设为1

    {% for item in todo_list %} 
        <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}
    View Code

    ② forloop.counter0 表示循环的次数,它从0开始计数,第一次循环设为0

    {% for item in todo_list %} 
        <p>{{ forloop.counter0 }}: {{ item }}</p>
    {% endfor %}
    View Code

    ③ forloop.revcounter  示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1

    {% for item in todo_list %} 
        <p>{{ forloop.revcounter }}: {{ item }}</p>
    {% endfor %}
    View Code

    ④ forloop.revcounter0 类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0

    {% for item in todo_list %} 
        <p>{{ forloop.revcounter0 }}: {{ item }}</p>
    {% endfor %}
    View Code

    ⑤ forloop.first 当第一次循环时值为True,在特别情况下很有用)

    {% for object in objects %} 
         {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} 
         {{ object }} 
        </li>
    {% endfor %}
    View Code

    ⑥ forloop.last 当最后一次循环时值为True 

    {% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}
    View Code

    ⑦ forloop.parentloop 在嵌套循环中表示父循环的forloop:

    {% for country in countries %} 
        <table>
         {% for city in country.city_list %} 
            <tr>
                <td>Country #{{ forloop.parentloop.counter }} </td>
                <td>City #{{ forloop.counter }}</td>
                <td>{{ city }}</td>
            </tr>
         {% endfor %} 
        </table>
    {% endfor %}
    View Code

    3、继承
    ①模板继承允许你建立一个基本的”骨架”模板, 它包含你所有最常用的站点元素 并 定义了一些可以被子模板覆盖的block。
    注:一个html页面只能继承一个父模板,不能继承多个

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}{% endblock %}</title>
        <style>
            .body-header{
                background-color: black;
            }
        </style>
    </head>
    <body>
    #父模板(master.html)
    {# 指定继承的模板 #}
    {% extends 'master.html' %}
     
    {# 指定替换的位置 #}
    {% block title %}
        tp1
    {% endblock %}
     
    {# 指定替换的位置 #}
     {% block content %}
        <p>tp1</p>
     {% endblock %}
    #HTML页面

    ②模板导入定制的组件include

    <form>
        <input type="text" name="user"/>
        <input type="submit" value="提交"/>
    </form>
    #组件(tag.html)
    {# 指定继承的模板 #}
    {% extends 'master.html' %}
     
    {# 指定替换的位置 #}
    {% block title %}
        tp1
    {% endblock %}
     
    {# 指定替换的位置 #}
    {% block content %}
        <p>tp1</p>
     
        {# 导入单独组件 #}
        {% include 'tag.html' %}
    {% endblock %}
    #HTML页面

    4、Simplelistfilter
    有时候我们需要在html上对后台渲染的页面进行二次处理,比如把字符串的首字母大写、字符进行计算操作等。
    (1)django默认自带方法

    {{ item.event_start|date:"Y-m-d H:i:s"}}    #日期格式进行转换
    {{ bio|truncatewords:"30" }}                  #取字符串前30位
    {{ my_list|first|upper }}                     #第一个字符大写             
    {{ name|lower }}                                #所有字符小写
    View Code

    (2)自定义simple_tag、filter
    ① 在app中创建templatetags文件夹
    ② templatetags中创建任意 .py 文件,如:handle.py

    from django import template
    from django.utils.safestring import mark_safe
     
    register = template.Library()
     
    @register.simple_tag()
    def sub(a1,a2):    #能添加多个参数
        return a1 + a2
     
    @register.filter()  
    def lzl(a1,a2):    #只能传入两个参数
        return a1 + a2
    #handle.py

    ③ 在settings中配置当前app,不然django无法找到自定义的simple_tag

    INSTALLED_APPS = (
              ......
        'cmdb',
    )
    #settings.py

    ④ 导入和使用simple_tag、filter

    {# 导入py文件名 #}
    {% load handle %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
            <div>{{ name|lower }}</div>
            <div>{{ name|upper }}</div>
     
            {% sub 1 2 %}
     
            {{ 'hello'|lzl:'world'}}
    </body>
    </html>
     
    {#页面内容#}
    {#3 helloworld#}
    #html

    (3)django数据库choice获取字段

    device_status_choices = (
            (1, '上架'),
            (2, '在线'),
            (3, '离线'),
            (4, '下架'),
        )
        device_type_id = models.IntegerField('设备类型',choices=device_type_choices, default=1)
     <td colspan="4">{{ response.data.asset.get_device_status_id_display }}</td>
    View Code

     二、分页 

    1、简单分页
    涉及xss攻击,需要用到mark_safe方法,使用此方法字符串传输到后端后,已html形式显示,而非字符串
    分页数进行定制,添加上一页、下一页,增加跳转功能,实现分页的完整功能 

      ① 设定每页显示数据条数
      ② 用户输入页码(第一页、第二页...)
      ③ 设定显示多少页号
      ④ 获取当前数据总条数
      ⑤ 根据设定显示多少页号和数据总条数计算出,总页数
      ⑥ 根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
      ⑦ 在数据表中根据起始位置取值,页面上输出数据
      ⑧ 输出分页html,如:[上一页][1][2][3][4][5][下一页]

    from app01 import views
    urlpatterns = [
                .....
        url(r'^user_list/', views.user_list),
    ]
    #urls.py
    LIST = []
    for i in range(109):
        LIST.append(i)
    
    from django.utils.safestring import  mark_safe   #
    def user_list(request):
        current_page = request.GET.get('p',1)  # 通过输入p页,利用get方法获取当前页码。不输入默认为第1页。得到的是一个字符串。
        current_page = int(current_page)       # 把字符串 --> 数字
    
        start = (current_page-1)*10            # 起始页
        end = current_page*10                  # 结束页
        data = LIST[start:end]                 # 起始页--结束页的所有数据
    
        all_count = len(LIST)                  # 总数据个数
        total_count,y = divmod(all_count,10)   # 总页面数,每页多少条数据;divmod():整除,余数
        if y :                                 # 存在余数,总页面数+1
            total_count +=1
        
        pager_num = 11                         # (显示的)页码数
        page_list = []                         # 
        if total_count < pager_num :           # ①总页面数 <(显示的)页码数
            start_index = 1
            end_index = total_count + 1
        else:                                  # ②总页面数 >=(显示的)页码数
            if current_page <= pager_num/2:                      #【开头】
                start_index = 1 # 首页
                end_index = pager_num + 1
            elif current_page + (pager_num-1)/2 >= total_count:  #【中间】
                start_index = total_count - (pager_num-1)
                end_index = total_count + 1
            else:                                                #【结尾】
                start_index = current_page - (pager_num-1)/2
                end_index = current_page + (pager_num-1)/2 + 1 #最后一页
    
        # 上下页码
        if current_page == 1:
            prev = '<a class="page" href="javascript:void(0)">上一页</a>'  # 什么都不干
        else:
            prev =  '<a class="page" href="/user_list/?p=%s">上一页</a>'%(current_page-1)
        page_list.append(prev)
        for i in range(int(start_index),int(end_index)):  #循环所有页码,选中的页码(当前页)改变样式,没选中的不改变样式
            if i == current_page:
                temp = '<a class="page active" href="/user_list/?p=%s">%s</a>'%(i,i)
            else:
                temp = '<a class="page" href="/user_list/?p=%s">%s</a>'%(i,i)
    
            page_list.append(temp)
        if current_page == total_count:
            nex = '<a class="page" href="javascript:void(0)">下一页</a>'  # 什么都不干
        else:
            nex = '<a class="page" href="/user_list/?p=%s">下一页</a>'%(current_page+1)
        page_list.append(nex)
    
        # 跳转 可以写到前端
        jump = '''
        <input type="text" /><a onclick="jumpTo(this,'/user_list/?p=');">GO</a>
        <script>
            function jumpTo(ths,base) {
                var val = ths.previousSibling.value;
                location.href = base + val;
            }
        </script>
        '''
        page_list.append(jump)
    
        page_str = mark_safe(''.join(page_list))  # mark_safe(防止XSS攻击,否侧page_str传到前端显示的是字符串,而不是html语言)
                                                  # 另一种方式在前端做
                                                  # {{ page_str|safe }}
    
                                                  #(''.join(page_list)):将所有的页码以空字符串进行拼接
        return render(request,'user_list.html',{'li':data,'page_str':page_str})
    #views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .pagination .page{
                display: inline-block;
                padding: 5px;
                background-color: cyan;
                margin: 5px;
            }
            .pagination .page.active{
                background-color: brown;
                color: white;
            }
        </style>
    </head>
    <body>
        <ul>
            {% for item in li %}
                <li>{{ item }}</li>
            {% endfor %}
        </ul>
        <div class="pagination">
            {{ page_str }}
        </div>
    </body>
    </html>
    #user_list.html

    改进:页码代码跟业务代码分开,创建class类调用,最好单独创建目录分开

    from app01 import views
    urlpatterns = [
                .....
        url(r'^user_list/', views.user_list),
    ]
    #urls.py
    LIST = []
    for i in range(199):
        LIST.append(i)
    
    class Page:
        def __init__(self, current_page, data_count, per_page_count=10, pager_num=7):
            self.current_page = current_page
            self.data_count = data_count
            self.per_page_count = per_page_count
            self.pager_num = pager_num
    
        @property   # 利用属性方法:把方法变成静态属性
        def start(self):
            return (self.current_page - 1) * self.per_page_count
    
        @property
        def end(self):
            return self.current_page * self.per_page_count
    
        @property
        def total_count(self):
            v, y = divmod(self.data_count, self.per_page_count)
            if y:
                v += 1
            return v
    
        def page_str(self, base_url):
            page_list = []
    
            if self.total_count < self.pager_num:   #self调用方法是不用加 ()
                start_index = 1
                end_index = self.total_count + 1
            else:
                if self.current_page <= (self.pager_num + 1) / 2:
                    start_index = 1
                    end_index = self.pager_num + 1
                else:
                    start_index = self.current_page - (self.pager_num - 1) / 2
                    end_index = self.current_page + (self.pager_num + 1) / 2
                    if (self.current_page + (self.pager_num - 1) / 2) > self.total_count:
                        end_index = self.total_count + 1
                        start_index = self.total_count - self.pager_num + 1
    
            if self.current_page == 1:
                prev = '<a class="page" href="javascript:void(0);">上一页</a>'
            else:
                prev = '<a class="page" href="%s?p=%s">上一页</a>' % (base_url, self.current_page - 1,)
            page_list.append(prev)
    
            for i in range(int(start_index), int(end_index)):
                if i == self.current_page:
                    temp = '<a class="page active" href="%s?p=%s">%s</a>' % (base_url, i, i)
                else:
                    temp = '<a class="page" href="%s?p=%s">%s</a>' % (base_url, i, i)
                page_list.append(temp)
    
            if self.current_page == self.total_count:
                nex = '<a class="page" href="javascript:void(0);">下一页</a>'
            else:
                nex = '<a class="page" href="%s?p=%s">下一页</a>' % (base_url, self.current_page + 1,)
            page_list.append(nex)
    
            jump = """
            <input type='text'  /><a onclick='jumpTo(this, "%s?p=");'>GO</a>
            <script>
                function jumpTo(ths,base){
                    var val = ths.previousSibling.value;
                    location.href = base + val;
                }
            </script>
            """ % (base_url,)
    
            page_list.append(jump)
    
            page_str = mark_safe("".join(page_list))
    
            return page_str
    #pagination.py
    from django.utils.safestring import  mark_safe
    def user_list(request):
        current_page = request.GET.get('p', 1)
        current_page = int(current_page)
        page_obj = Page(current_page,len(LIST))
    
        data = LIST[page_obj.start:page_obj.end]
    
        page_str = page_obj.page_str("/user_list/")
    
        return render(request, 'user_list.html', {'li': data,'page_str': page_str})
    #views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .pagination .page{
                display: inline-block;
                padding: 5px;
                background-color: cyan;
                margin: 5px;
            }
            .pagination .page.active{
                background-color: brown;
                color: white;
            }
        </style>
    </head>
    <body>
        <ul>
            {% for item in li %}
                <li>{{ item }}</li>
            {% endfor %}
        </ul>
        <div class="pagination">
            {{ page_str }}
        </div>
    </body>
    </html>
    #user_list.html

    三、Cookie 

    1、概述
    Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。(可以叫做浏览器缓存:Cookie就是一段字符串,保存于本机电脑上。)
    ① 获取Cookie

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

    ② 设置Cookie

    rep = HttpResponse(...) 或 rep = render(request, ...) #return的对象
      
    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传输改为True
            httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
     
    补充:
    # max_age 10秒失效
    result.set_cookie('username',u,max_age=10)
     
    # expires 设置失效日期
    import datetime
    current_date = datetime.datetime.utcnow()  # utcnow()当前时间
    current_date = current_date + datetime.timedelta(seconds=5) # timedelta时间差
    result.set_cookie('username',u,expires=current_date)
     
    # 加密(带签名的)
    obj = HttpResponse('s')
    obj.set_signed_cookie('username',"kangbazi",salt="asdfasdf") #加密
    request.get_signed_cookie('username',salt="asdfasdf")   # 解密
    
    注:由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie
    <script src='/static/js/jquery.cookie.js'></script>
    $.cookie("list_pager_num", 30,{ path: '/' });   #key vaule  字典
    View Code

    2、用户登录
    利用cookie做用户登录页面,只有登录成功才能进入到后台管理

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>欢迎登录:{{ current_user }}</h1>
    </body>
    </html>
    #index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <form action="/login/" method="POST">
            <input type="text" name="username" placeholder="用户名" />
            <input type="password" name="pwd" placeholder="密码" />
            <input type="submit" />
        </form>
    </body>
    </html>
    #login.html
    user_info = {
        'solo':{'pwd':'123456'}
    }
     
    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        if request.method == 'POST':
            u = request.POST.get('username')
            p = request.POST.get('pwd')
            dic = user_info.get(u)
            if not dic:
                return render(request,'login.html')
            if dic['pwd']== p:
                result = redirect('/index/')
                result.set_cookie('username',u)     #设置cookie值
                return result
            else:
                return render(request, 'login.html')
     
    def index(request):
        v = request.COOKIES.get('username')         #获取cookie值
        if not v :
            return redirect('/login/')
        return render(request,'index.html',{'current_user':v})
    #views.py

    3、定制分页
    根据用户选择的数字,显示页面的数量

    <body>
        <ul>
            {% for item in li %}
                <li>{{ item }}</li>
            {% endfor %}
        </ul>
        <div>
            <select id='pg' onchange="ChangePageSize(this)">   #给选中的页面增加一个事件
                <option value="10">10</option>
                <option value="30">30</option>
                <option value="50">100</option>
            </select>
        </div>
        <div class="pagination">
            {{ page_str }}
        </div>
        <script src="/static/jquery-1.12.4.js"></script>
        <script src="/static/jquery.cookie.js"></script>  #注意顺序
        <script>
     
            $(function () {   # 页面加载完成后执行此方法
                var v = $.cookie('per_page_count',{'path':'/user_list/'});#获取选中的值,设置为新一页的默认值;路径:只有当前页面受影响
                $('#pg').val(v);
            });
     
            function ChangePageSize(ths) {
                var v = $(ths).val(); # 获取用户当前选择的值
                $.cookie('per_page_count',v,{'path':'/user_list/'});
                location.reload()
            }
        </script>
    </body>
    #user_list.html
    from django.utils.safestring import  mark_safe
    def user_list(request):
        current_page = request.GET.get('p', 1)
        current_page = int(current_page)
     
        per_page_count = request.COOKIES.get('per_page_count',10)   #获取cookie值
        per_page_count = int(per_page_count)
     
        page_obj = Page(current_page,len(LIST),per_page_count)
     
        data = LIST[page_obj.start:page_obj.end]
     
        page_str = page_obj.page_str("/user_list/")
     
        return render(request, 'user_list.html', {'li': data,'page_str': page_str})
    # views.py

    4、登录认证(装饰器)
    ①FBV

    def auth(func):
        def inner(request,*args,**kwargs):
            v = request.COOKIES.get('username')  # 获取cookie值
            if not v:
                return redirect('/login/')
            return  func(request,*args,**kwargs)
        return inner
    
    @auth               #认证装饰
    def index(request):
        v = request.COOKIES.get('username')
        return render(request, 'index.html', {'current_user': v})
    View Code

    ②CBV

    def auth(func):
        def inner(request,*args,**kwargs):
            v = request.COOKIES.get('username')  # 获取cookie值
            if not v:
                return redirect('/login/')
            return  func(request,*args,**kwargs)
        return inner
    
    from django import views
    from django.utils.decorators import method_decorator
    
    @method_decorator(auth,name='dispatch')     #第一种方式
    class Order(views.View):
    
        # @method_decorator(auth)                   #第二种方式
        # def dispatch(self, request, *args, **kwargs):
        #     return super(Order,self).dispatch(request, *args, **kwargs)
    
        # @method_decorator(auth)                   #单独添加
        def get(self,reqeust):
            v = reqeust.COOKIES.get('username111')
            return render(reqeust,'index.html',{'current_user': v})
    
        def post(self,reqeust):
            v = reqeust.COOKIES.get('username111')
            return render(reqeust,'index.html',{'current_user': v})
    View Code

    三、Session   
    1、概述
    两者区别:Cookie是保存在用户浏览器端的键值对,Session是保存在服务器端的键值对;Cookie做用户验证的时,敏感信息不适合放在Cookie中,别人可以分析存放在本地的Cookie并进行Cookie欺骗,考虑到安全应当使用Session;用户验证时两者要结合使用,Session可保存到文件,内存,数据库任意地方。 (session 保存于服务器,用来保存用户的会话信息,依赖于Cookies)
    ① 获取

    # 获取Session中数据
    request.session['k1']
    request.session.get('k1', None)
    View Code

    ② 生成

    # 生成Session中数据
    request.session['k1'] = 123
    request.session.setdefault('k1', 123)  # 存在则不设置
    View Code

    ③ 删除

    # 删除Session中某条数据
    del request.session['k1']
     
    # 删除当前用户的所有Session数据
    request.session.delete("session_key")
    request.session.clear()         #注销时可用
    View Code

    ④ 键值对

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

    ⑤ 超时时间

    # 设置超时时间
    request.session.set_expiry(value)       #默认超时时间为两周
    *如果value是个整数,session会在些秒数后失效。
    *如果value是个datatime或timedelta,session就会在这个时间后失效。
    *如果value是0, 用户关闭浏览器session就会失效。
    *如果value是None, session会依赖全局session失效策略。
    View Code

    ⑥ 其他

    # 用户session的随机字符串
    request.session.session_key
     
    # 将所有Session失效日期小于当前日期的数据删除
    request.session.clear_expired()
     
    # 检查 用户session的随机字符串 在数据库中是否 一般用不到
    request.session.exists("session_key")
    View Code

    2、用户登录
    利用Session做用户登录页面,只有登录成功才能进入到后台管理

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/login/" method="post">
            <input type="text" name="user" />
            <input type="text" name="pwd" />
            <input type="checkbox" name="session" value="1"/> 保存1个月
            <input type="submit" value="提交" />
        </form>
    </body>
    </html>
    #login.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {{ request.session.username }}
    </body>
    </html>
    #index.html
    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        elif request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            if user == 'root' and pwd == "123":
                # 生成随机字符串
                # 写到用户浏览器Cookie
                # 保存到Session中
                # 在随机字符串对应的字典中设置相关内容...
                request.session['username'] = user
                request.session['if_login'] = True        #可不加 直接判断username也可以
                if request.POST.get('session') == '1':    #单独设置超时时间,当前session生效,不影响全局
                    request.session.set_expiry(10)        #10秒
                return redirect('/index/')
            else:
                return redirect('/login/')
     
    def index(request):
        # 获取当前用户的随机字符串
        # 根据随机字符串获取对应信息
        if request.session.get('if_login'):
            return render(request, 'index.html')
        else:
            return redirect('/login/')
    #vars.py

    3、Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
    ①数据库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")
     
            request.session.set_expiry(value)
                * 如果value是个整数,session会在些秒数后失效。
                * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                * 如果value是0,用户关闭浏览器session就会失效。
                * 如果value是None,session会依赖全局session失效策略。
    View Code

    ②缓存存储Session
    可以设置为Memcache缓存,默认不支持redis(可以使用网上插件)

    #本地内存存储session
    配置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,默认修改之后才保存
    
    #Memcache缓存
    配置settings.py
    
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'db'  # 使用的缓存别名,此处别名依赖缓存的设置
    
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        },
        'db': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                '172.19.26.240:11211',
                '172.19.26.242:11211',
            ]
        }
    }
    View Code

    ③文件存储Session

    #文件session
    配置 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,默认修改之后才保存
    View Code

    ④缓存+数据库Session

    #缓存+数据库Session
    数据库用于做持久化,缓存用于提高效率,先去缓存中取数据,缓存没有再去数据库中取,然后在缓存中存一份
    
    配置settings.py
    
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'  # 引擎
    View Code

    ⑤加密cookie Session

    #加密cookie Session
    数据都存在于客户端
    配置settings.py
    
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'  # 引擎
    #注:当使用Session时,需要执行makemigrations和 migrate,数据库上会自动生成django_session数据表
    View Code

    Session&Cookie 总结

    Cookie就是一段字符串,保存于本机电脑上。
    session 保存于服务器,用来保存用户的会话信息,依赖于Cookies

    流程:举个例子,咱们在登录一个网站后,拿JD举例,如果我登录进去之后,在想点击订单的时候。server断怎么判断我是“我”,而不是其他人呢?
    Http是短连接,那么Server端肯定有一个保存我登录状态的地方(session),那server怎么判断是我发送过来的请求呢?就是通过Cookie!
    当客户端访问过来后,server端会在IE里生成一个Cookie,当访问过来的时候就可以通过Cookie进行判断

    在session中,我们可以设置多个key:value的值,我们可以在session设置,当用户登录的时候,我们把的用户名,增加到session中,那么用户携带cookie访问的时候,我们就能判断是哪个一用来访问的!

    Session和Cookie好处:Cookie可以理解为一个身份证ID,你只能拿着他去和Server端进行通信,如果你没有这个ID那么server端也不知道你是谁!(我在写博客的时候在做Cookie和Session的实验,把Cookie删掉了!当我保存的时候直接给我提出来了,为什么呢?就是因为,server端不知道我是谁了,我已经没有密钥了。)

    所以,只要Session和Cookie任意一方失效,就可以理解为:Cookie失效就相当于身份证ID过期,需要重新认证才可以继续使用。Session失效就相当于银行里的数据标识此ID无效,也需要重新申请。

  • 相关阅读:
    LeetCode:Container With Most Water
    c#编写的基于Socket的异步通信系统
    关于Thread类中三个interrupt方法的研究与学习(转)
    使用svnkit 的相关实例及相关问题汇总
    创业早期,联合创始人如何避免窝里反?(转)
    程序员解决问题的60个策略(转)
    码农和程序员之间的5个关键差异(转)
    LayoutInflater的使用
    2014年中国95家企业入围世界500强,超日本
    How to get the source code of the chromium of the specified revision
  • 原文地址:https://www.cnblogs.com/liwei1153300111/p/8377778.html
Copyright © 2020-2023  润新知