• python之路_django分页及session介绍


    一、分页介绍

    1、django 分页器

      在django框架中,为我们提供了分页器Paginator,引入的方式为:from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger,其中EmptyPage为请求页码超出最大的页码抛出的异常,PageNotAnInteger为请求的页码不是一个合法的数字时抛出的异常。应用实例介绍如下:

    后端函数部分:

    from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
    def index(request):
        book_list=Book.objects.all()         #取到的所有数据
        paginatorObj=Paginator(book_list,5)  #实例化Paginator对象,接收两个参数:所以数据,每页显示的数据条数
        '''
        paginator对象三个属性:
        print(paginatorObj.count)           数据总条数
        print(paginatorObj.num_pages)       总页码数
        print(paginatorObj.page_range)      页码数的范围:range(1,paginatorObj.num_pages+1)
        '''
      
        current_num = request.GET.get("page", 1)              #获取请求的页数,默认为1
        current_num = int(current_num)
    
        page_count=11                                         #显示的分页数
        if paginatorObj.num_pages<=page_count:
            pageRange=paginatorObj.page_range
        else:
            if current_num-5<=1:
                pageRange=range(1,page_count+1)
            elif current_num+5>=paginatorObj.num_pages:
                pageRange = range(paginatorObj.num_pages-page_count+1, paginatorObj.num_pages + 1)
            else:
                pageRange = range(current_num-5, current_num+6)
    
        try:
            pageObj=paginatorObj.page(current_num)
            '''
            页对象的属性:
            print(pageObj.has_next())               是否有下一页,返回True或者False
            print(pageObj.next_page_number())       下一页页码数
            print(pageObj.has_previous())           是否有上一页,返回True或者False
            print(pageObj.previous_page_number())   上一页页码数
           '''
           
        except Exception:                            #主要解决用户输入非法页码时产生的异常
            pageObj = paginatorObj.page(1)
        book_list=pageObj.object_list                #获取当前页对象包含的数据对象
        return render(request,"index.html",locals())

    html文件部分:

    <body>
    <div class="container">
        <h4>分页器</h4>
        <ul>
            {% for book in book_list %}
                <li>{{ book.tittle }} -----{{ book.price }}</li>
            {% endfor %}
        </ul>
    
        <ul class="pagination" id="pager">
                 <li class="previous"><a href="/index/?page={{ 1 }}">首页</a></li>
            {% if pageObj.has_previous %}
                <li class="previous"><a href="/index/?page={{ pageObj.previous_page_number }}">上一页</a></li>
            {% else %}
                <li class="previous disabled"><a href="#">上一页</a></li>
            {% endif %}
    
    
            {% for num in pageRange %}
    
                {% if num == current_num %}
                    <li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li>
                {% else %}
                    <li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li>
                {% endif %}
            {% endfor %}
    
    
    
            {% if pageObj.has_next %}
                <li class="next"><a href="/index/?page={{ pageObj.next_page_number }}">下一页</a></li>
            {% else %}
                <li class="next disabled"><a href="#">下一页</a></li>
            {% endif %}
                <li class="previous"><a href="/index/?page={{ paginatorObj.num_pages }}">尾页</a></li>
    
        </ul>
    </div>
    </body>

    2、自定义分页器

    如下实例为自定义分页:

    """
    分页组件使用示例:
    def index(request):
        obj = Pagination(request.GET.get('page',1),len(USER_LIST),request.path_info)
        page_user_list = USER_LIST[obj.start:obj.end]
        page_html = obj.page_html()
        return render(request,'index.html',{'users':page_user_list,'page_html':page_html})
    
    """
    
    
    class Pagination(object):
        def __init__(self,current_page,all_count,base_url,per_page_num=10,pager_count=11):
            """
            封装分页相关数据
            :param current_page: 当前页
            :param all_count:    数据库中的数据总条数
            :param per_page_num: 每页显示的数据条数
            :param base_url: 分页中显示的URL前缀
            :param pager_count:  最多显示的页码个数
            """
    
            try:
                current_page = int(current_page)
            except Exception as e:
                current_page = 1
            if current_page <1:
                current_page = 1
    
            self.current_page = current_page
    
            self.all_count = all_count
            self.per_page_num = per_page_num
    
            self.base_url = base_url
    
            # 总页码
            all_pager, tmp = divmod(all_count, per_page_num)
            if tmp:
                all_pager += 1
            self.all_pager = all_pager
    
    
            self.pager_count = pager_count
            self.pager_count_half = int((pager_count - 1) / 2)
    
        @property
        def start(self):
            return (self.current_page - 1) * self.per_page_num
    
        @property
        def end(self):
            return self.current_page * self.per_page_num
    
        def page_html(self):
            # 如果总页码 < 11个:
            if self.all_pager <= self.pager_count:
                pager_start = 1
                pager_end = self.all_pager + 1
            # 总页码  > 11
            else:
                # 当前页如果<=页面上最多显示11/2个页码
                if self.current_page <= self.pager_count_half:
                    pager_start = 1
                    pager_end = self.pager_count + 1
    
                # 当前页大于5
                else:
                    # 页码翻到最后
                    if (self.current_page + self.pager_count_half) > self.all_pager:
                        pager_end = self.all_pager + 1
                        pager_start = self.all_pager - self.pager_count + 1
                    else:
                        pager_start = self.current_page - self.pager_count_half
                        pager_end = self.current_page + self.pager_count_half + 1
    
            page_html_list = []
    
            first_page = '<li><a href="%s?page=%s">首页</a></li>' % (self.base_url,1,)
            page_html_list.append(first_page)
    
            if self.current_page <= 1:
                prev_page = '<li><a href="#">上一页</a></li>'
            else:
                prev_page = '<li><a href="%s?page=%s">上一页</a></li>' % (self.base_url,self.current_page - 1,)
    
            page_html_list.append(prev_page)
    
            for i in range(pager_start, pager_end):
                if i == self.current_page:
                    temp = '<li class="active"><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
                else:
                    temp = '<li><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
                page_html_list.append(temp)
    
            if self.current_page >= self.all_pager:
                next_page = '<li><a href="#">下一页</a></li>'
            else:
                next_page = '<li><a href="%s?page=%s">下一页</a></li>' % (self.base_url,self.current_page + 1,)
            page_html_list.append(next_page)
    
            last_page = '<li><a href="%s?page=%s">尾页</a></li>' % (self.base_url,self.all_pager,)
            page_html_list.append(last_page)
    
            return ''.join(page_html_list)

      上述类中page_html()函数返回的是分页列表中包含li标签的字符串,替换到相应html文件的中的方式如下:

    函数获取字符串:

    字符串转换成html:

    二、session介绍  

      cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。

      问题来了,基于http协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的cookie就起到桥接的作用。我们可以给每个客户端的cookie分配一个唯一的id,这样用户在访问时,通过cookie,服务器就知道来的人是“谁”。然后我们再根据不同的cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。

      结而言:cookie弥补了http无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本。

      另外,上述所说的cookie和session其实是共通性的东西,不限于语言和框架

    1、cookie与session比较

      (a)cookie是保存在浏览器端的键值对,而session是保存的服务器端的键值对,但是依赖cookie。

      (b)以登录为例,cookie为通过登录成功后,设置明文的键值对,并将键值对发送客户端存,明文信息可能存在泄漏,不安全;session则是生成随机字符串,发给用户,并写到浏览器的cookie中,同时服务器自己也会保存一份。

      (c)在登录验证时,cookie:根据浏览器发送请求时附带的cookie的键值对进行判断,如果存在,则验证通过;session:在请求用户的cookie中获取随机字符串,根据随机字符串在session中获取其对应的值进行验证

    原理如下:

    2、session的分类

      如上,根据session在服务器中的保存位置分如下5种:

    (1)数据库session

      顾名思义,session的数值是保存在数据库中的,Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。使用此类型session之前需要通过执行如下两个命令进行创建session需要的表。如下:

    python manage.py makemigrations
    python manage.py migrate

      此类型session的基本文件配置如下,在setting.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,默认修改之后才保存(默认)

      session的使用如下:

    设置:

    获取:

    删除:

    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失效策略。

    (2)缓存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,默认修改之后才保存

    (3)文件session

    (4)缓存+数据库session

    (5)加密cookie session

  • 相关阅读:
    嵌入式系统移植三部曲 王晓峰
    嵌入式系统移植三部曲 李炎朔
    ser and client.c 王晓峰
    李炎朔 编程分析
    嵌入式系统移植三步曲 赵晓晓
    嵌入式系统移植三步曲 孟明明
    现在 搞技术确实越来越不值钱了
    Linux C局域网通信程序 刘志卿
    Firefox全面兼容中国银联“在线支付”
    Linux常识型试题
  • 原文地址:https://www.cnblogs.com/Ebola-/p/8734115.html
Copyright © 2020-2023  润新知