zoukankan      html  css  js  c++  java
  • python自动化开发-[第十九天]-分页,cookie,session

    今日概要:

      1、cookie和session

      2、csrf 跨站请求伪造

      3、自定义分页

    一、上节回顾:

      http请求的本质:

    	- Http请求本质
    	浏览器(socket客户端):
    		2. socket.connect(ip,端口)
    		3. socket.send("http://www.xiaohuar.com/index.html....")
    		   规则:http协议
    			     GET请求:
    					"GET /index.html?k1=1&k2=2 Http/1.1
    host:www.xiaohuar.com
    content-type:application/json
    
    "
    				 
    					请求头和请求体使用
    
    分割,前面头,后面是体
    				 POST请求:
    					"POST /index.html?k1=1&k2=2 Http/1.1
    host:www.xiaohuar.com
    content-type:application/json
    
    username=alex&pwd=123123"
    				 
    					请求头和请求体使用
    
    分割,前面头,后面是体
    					
    				www.xiaohuar.com/index.html?k1=1&k2=2
    		6. 获取相应
    			响应头,响应体 = data.split('
    
    ')
    			
    		7. 断开连接
    	网站(socket服务端):
    		1. 服务端运行: ip,端口
    		4. 字符串 = server.recv()
    		
    			头,体 = data.split("
    
    =")
    			
    			request.POST.get()
    			
    		5. 服务端响应:
    			conn.send('......')
    			
    			响应头:
    			
    			响应体:
    				
    		7. 断开连接
    			
    总结:
    
    	a. Http请求中本质都是字符串
    	b. Http请求短连接(请求,响应断开连接)
    	c. 请求和响应都有:头、体
    		请求:
    			请求头
    			
    
    
    			请求体
    		响应:
    			响应头
    			
    
    
    			响应体
    				<html>
    					....
    				</html> 

      ORM表操作复习:

    	- 创建表: 业务线
    	
    	- models.xx.objects.create(name=‘canada')
    	- models.xx.objects.create(**dic)
    	
    	- models.xx.objects.filter(id__gt=1).delete()
    	- models.xx.objects.filter(id=1).delete()
    	- models.xx.objects.exclude(id=1).delete()
    	
    	- models.xx.objects.filter(id=1).update(name='ddd')
    	- models.xx.objects.filter(id=1).update(**dic)
    	
    	- 创建表: 
    		业务线
    		主机表
    			id host port bs
    			
    	# queryset = [对象,对象,...]
    	- objs = models.xx.objects.all()
    	  for row in objs:
    		row.id
    		row.host
    		row.port
    		row.bs.name
    		
    	# queryset = [{},{},...]
    	- objs = models.xx.objects.all().values('id','host','port','bs__name')
    	  for row in objs:
    		row['id']
    		row['bs__name']
    		
    	# queryset = [(1,1.1.11,80,'Web'),(),()...]
    	- objs = models.xx.objects.all().values_list('id','host','port','bs__name') #正向查找bs的名字
    	  for row in objs:
    		row[0]
    		row[1]
    			
    model操作	
    	- 创建表: 
    		用户表(id, user,pwd,email,mm)
    		业务线(id, name) # 用户表_set
    		主机表(id host port bs)
    		用户业务线关系表(id  uid  bid)   ******
    					      1   22    1
    					      2   22    11
    	-   obj = modes.userinfo.objects.filter(user='日语哥').first()
    		obj.mm.add(1)
    		obj.mm.add(11)
    		# 日语哥负责的所有业务线 -> [业务线对象,业务线对象,]
    		queryset = obj.mm.all() 
    		for row in queryset:
    			row.id
    			row.name
    		
    		
    	- 二手车业务线是由那些人负责 通过对象_set方法进行反向查找
    		obj = models.business_unit.objects.filter(name='二手车').first()
    		queryset = obj.userinfo_set.all() #[用户对象,用户对象,]
    		for row in queryset:
    			row.user
    			row.pwd 

    二、cookie和session 

       cookie

      1、cookie是什么?    

        - 保存在客户端浏览器上的键值对 {k:v}
        - cookie依附在请求头或响应头中出现
        - 发送请求时,会自动携带自己网站的cookie

      2、应用场景:

        1、投票(通过id进行累加) -->如果用户禁用cookie就存在问题

        2、登录

        3、cmdb中用户选择一页表格显示多少行,可以通过cookie搞定

      3、获取cookie 

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

      4、设置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 

      1、什么是session?

        保存在服务端的键值对

      2、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")
     
            request.session.set_expiry(value)
                * 如果value是个整数,session会在些秒数后失效。
                * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                * 如果value是0,用户关闭浏览器session就会失效。
                * 如果value是None,session会依赖全局session失效策略。
    数据库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. 使用
     
        同上
    View Code

       3、session认证装饰器:  

    def auth(func):
        '''判断是否登录装饰器'''
        def inner(request,*args,**kwargs):
            v = request.session.get('user')
            if not v:
                return redirect('/login.html')
            return func(request, *args,**kwargs)
        return inner
    

     三、csrf跨站请求伪造

      1、简介

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

      全局:

        中间件 django.middleware.csrf.CsrfViewMiddleware

      局部:

    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。 --> 前提条件settings未设置csrf中间件
    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

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

      2、应用

        普通表单:   

    veiw中设置返回值:
      return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
         或者
         return render(request, 'xxx.html', data)
      
    html中设置Token:
      {% csrf_token %}
    

        Ajax提交:

          1、基于请求体:     

    function ajaxSubmit() {
    	$.ajax({
    		url: "/icbc.html",
    		type: 'POST',
    		data: {'k1':'v1','k2':'v2','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val() },
    		success:function (arg) {
    			console.log(arg)
    		}
    	})
    }
    

           2、只能写在模版里       

    function ajaxSubmit() {
    	$.ajax({
    		url: "/icbc.html",
    		type: 'POST',
    		data: {'k1':'v1','k2':'v2','csrfmiddlewaretoken':"{{ csrf_token }}" },
    		success:function (arg) {
    			console.log(arg)
    		}
    	})
    }
    
    function ajaxSubmit() {
    	$.ajax({
    		url: "/icbc.html",
    		type: 'POST',
    		data: $('#f1').serialize(),
    		success:function (arg) {
    			console.log(arg)
    		}
    	})
    }
    

         以上都是放在请求体里

        3、放在请求头里

    基于请求头:
    a. 在cookie中获取csrftoken对应的值 l2kEqQLhR1gH0hh3ioZ1dfxT3iSwjXoKTf7GNFggJZ7E6DROB6k33L7vdqe5lV1v
    b. 发送请求时,放在请求头中也可以
    
    function ajaxSubmit() {
    	$.ajax({
    		url: "/icbc.html",
    		type: 'POST',
    		data: {'k1':'v1','k2':'v2'},
    		headers: {"X-CSRFToken": $.cookie('csrftoken')},
    		success:function (arg) {
    			console.log(arg)
    		}
    	})
    }

     四、自定义分页

      自定义一个初始化类:

      

    class Page(object):
        def __init__(self,current_page,all_count,base_url,per_page=10,pager_page_count=11):
            """
            分页初始化
            :param current_page: 当前页码
            :param per_page: 每页显示数据条数
            :param all_count: 数据库中总条数
            :param pager_page_count: 页面上最多显示的页码数量
            """
            self.base_url = base_url
            self.current_page = current_page
            self.per_page = per_page
            self.all_count = all_count
            self.pager_page_count = pager_page_count
            pager_count, b = divmod(all_count, per_page)
            if b != 0:
                pager_count += 1
            self.pager_count = pager_count
    
            half_pager_page_count = int(pager_page_count / 2)
            self.half_pager_page_count = half_pager_page_count
    
        @property
        def start(self):
            """
            数据获取值起始索引
            :return:
            """
            return (self.current_page - 1) * self.per_page
    
        @property
        def end(self):
            """
            数据获取值结束索引
            :return:
            """
            return self.current_page * self.per_page
    
        def page_html(self):
            """
            生成HTML页码
            :return:
            """
            # 如果数据总页码pager_count<11 pager_page_count
            if self.pager_count < self.pager_page_count:
                pager_start = 1
                pager_end = self.pager_count
            else:
                # 数据页码已经超过11
                # 判断: 如果当前页 <= 5 half_pager_page_count
                if self.current_page <= self.half_pager_page_count:
                    pager_start = 1
                    pager_end = self.pager_page_count
                else:
                    # 如果: 当前页+5 > 总页码
                    if (self.current_page + self.half_pager_page_count) > self.pager_count:
                        pager_end = self.pager_count
                        pager_start = self.pager_count - self.pager_page_count + 1
                    else:
                        pager_start = self.current_page - self.half_pager_page_count
                        pager_end = self.current_page + self.half_pager_page_count
    
            page_list = []
            if self.current_page <= 1:
                prev = '<a href="#">上一页</a>'
            else:
                prev = '<a href="%s?page=%s">上一页</a>' % (self.base_url,self.current_page - 1,)
            page_list.append(prev)
            for i in range(pager_start, pager_end + 1):
                if self.current_page == i:
                    tpl = '<a class="active" href="%s?page=%s">%s</a>' % (self.base_url,i, i,)
                else:
                    tpl = '<a href="%s?page=%s">%s</a>' % (self.base_url,i, i,)
                page_list.append(tpl)
    
            if self.current_page >= self.pager_count:
                nex = '<a href="#">下一页</a>'
            else:
                nex = '<a href="%s?page=%s">下一页</a>' % (self.base_url,self.current_page + 1,)
            page_list.append(nex)
            page_str = "".join(page_list)
            return page_str
    

        如何调用:

        

    from utils.pagination import Page
    def hosts(request):
        """
        主机列表
        :param request: 请求相关的所有数据
        :return:
        """
        # 当前页
        current_page = int(request.GET.get('page'))
        all_count = models.Host.objects.all().count()
        # page_obj = Page(current_page,all_count,'/hosts.html')
        page_obj = Page(current_page,all_count,request.path_info)
    
        host_list = models.Host.objects.all()[page_obj.start:page_obj.end]
        page_str = page_obj.page_html()
    
        return render(request,'hosts.html', {'host_list': host_list,'page_str':page_str})
    

       HTML端用法

        <div class="pagination1">
            {{ page_str|safe }}
        </div>
    

           

  • 相关阅读:
    3DMax的OFusion插件使用问题
    eclipse调试java调用matlab程序的7.17dll找不到的问题
    C++malloc,calloc,realloc,free函数
    北漂工作心得
    [置顶] 使用sping AOP 操作日志管理
    你不知道的Eclipse用法:使用Allocation tracker跟踪Android应用内存分配
    [置顶] 程序员扩充人脉那些事儿
    linux常见笔试题
    数学之路(3)-机器学习(3)-机器学习算法-神经网络[4]
    Android屏幕相关设置
  • 原文地址:https://www.cnblogs.com/liujiliang/p/7492622.html
Copyright © 2011-2022 走看看