• Django (二)


    一. cookie

    a. 简单应用

    def login(request):
        if request.method=="GET":
            return render(request,"login.html")
        else:
            name = request.POST.get("name")
            password = request.POST.get("password")
            if name == "alex" and password == "123":
                obj = redirect("/classes/")
                obj.set_cookie("ticket","123456",max_age=10)
                return obj
            else:
                return redirect("/login/")
    
    
    
    def classes(request):
        sk = request.COOKIES
        print(sk)
        if not sk:
            return redirect("/login/")
    View Code 

    b. 过期时间的两种格式

    方式一:
    obj.set_cookie("ticket","123456",max_age=10)
    
    方式二:
    import datetime
    from datetime import timedelta     #时间的加减
    ct = datetime.datetime.utcnow()   #获取当前日期
    v= timedelta(seconds=10)   #10秒
    value = ct + v
    
    obj.set_cookie("ticket","123456",expires=value)
    

    c. 限制路径

    obj.set_cookie("ticket","123456",max_age=10,path="/")   #所有路径都可以访问
    
    obj.set_cookie("ticket","123456",max_age=10,path="/class")   #只有class访问
    

    d. cookie签名

    #加
    obj.set_signed_cookie("ticket","123456",salt="abc")
    
    #解
    sk = request.get_signed_cookie("ticket",salt="abc")
    

    二. session

    流程:客户登录网址,验证成功后,服务端生成一个随机字符串和随机字符串对应的键值,然后把随机字符串通过cookie发送给客户端
    	 客户端拿着随机字符串通过cookir再次登陆,服务端拿着随机字符串和保存在本地的数据对应,以确定用户的登录状态
    
    Cookie是什么?
        保存在客户端浏览器上的键值对
    Session是什么?
        保存在服务端的数据(本质是键值对)
        {
            “aaaaa":{'id':1,'name':'于浩',email='xxxx'}
            "bbbbb":{'id':2,'name':'陈涛',email='0000'}
        }
        应用:依赖cookie
        作用:保持会话(Web网站)
        好处:敏感信息不会直接给客户端
        
        梳理:
            1. 保存在服务端的数据(本质是键值对)
            2. 配置文件中:
                - 存储位置
                - 超时时间、每次刷新更新时间
    View Code

    a. 简单示例

    用户访问http://127.0.0.1:8000/login/
    
    urlpatterns = [
    
        url(r'^index/', views.index),
        url(r'^login/', views.login),
    ]
    urls.py
    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            u = request.POST.get('user')
            p = request.POST.get('pwd')
            obj = models.UserAdmin.objects.filter(username=u,password=p).first()
            if obj:
                # 1. 生成随机字符串
                # 2. 通过cookie发送给客户端
                # 3. 服务端保存
                # {
                #   随机字符串1: {'username':'alex','email':x''...}
                # }
                request.session['username'] = obj.username
                return redirect('/index/')
            else:
                return render(request,'login.html',{'msg':'用户名或密码错误'})
    
    
    def index(request):
        # 1. 获取客户端端cookie中的随机字符串
        # 2. 去session中查找有没有随机字符
        # 3. 去session对应key的value中查看是否有 username
        v = request.session.get('username')
        if v:
            return HttpResponse('登录成功:%s' %v)
        else:
            return redirect('/login/')
    Views.py
    <!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="submit" value="提交">{{ msg }}
    </form>
    
    
    </body>
    </html>
    login.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        <h1>index page</h1>
    
    </body>
    </html>
    index.html

    三. cbv

    cbv(class-base-view)    基于类的视图
    fbv(func-base-view)     基于函数的视图

    a. 基本演示

    urlpatterns = [
       
        url(r'^login.html$', views.Login.as_view()),
    ]
    urls.py
    from django.views import View
    
    class Login(View):
    
        def dispatch(self, request, *args, **kwargs):
            print('before')
            obj = super(Login,self).dispatch(request,*args,**kwargs)
            print("after")
            return obj
    
        def get(self,request):
            return render(request,"login.html")
    
        def post(self,request):
            print(request.POST)
    
            return HttpResponse("Login.post")
    View.py

    四. 分页 

    a. django分页

    #浏览器访问
    http://127.0.0.1:8000/index.html/?page=9
    urlpatterns = [
     
        #django分页
        url(r'^index', views.index),
    ]
    urls.py
    #django 分页
    from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
    def index(request):
        current_page = request.GET.get("page")
        user_list = models.User_info.objects.all()
        paginator = Paginator(user_list,10)  #每页显示10条
    
        """
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        """
        try:
            posts = paginator.page(current_page)   #当前页
        except PageNotAnInteger as e:   #http://127.0.0.1:8000/index.html/?page=qqq 处理这种异常
            posts = paginator.page(1)
        except EmptyPage as e:  #http://127.0.0.1:8000/index.html/?page=-10  捕获这种异常
            posts = paginator.page(1)
    
    
        """
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
        """
    
        return render(request,"index.html",{"posts":posts})
    View.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>用户列表</h1>
        <ul>
            {% for row in posts.object_list %}
                <li>{{ row.name }}</li>
            {% endfor %}
        </ul>
        <div>
            {% if posts.has_previous %}
                <a href="/index.html/?page={{ posts.previous_page_number }}">上一页</a>
            {% endif %}
    
            {% for num in posts.paginator.page_range %}
                <a href="/index.html/?page={{ num }}">{{ num }}</a>
            {% endfor %}
    
            {% if posts.has_next %}
                <a href="/index.html/?page={{ posts.next_page_number }}">下一页</a>
            {% endif %}
        </div>
    
    </body>
    </html>
    index.html

    b. 自定义分页

    #浏览器访问
    http://127.0.0.1:8000/custom/?page=6
    urlpatterns = [
    
        #自定义分页
        url(r'^custom/', views.custom),
    ]
    urls.py
    from utils.pager import PageInfo
    #自定义分页
    def custom(request):
    
        #总页数
        all_count = models.User_info.objects.all().count()
    
        #用户当前想要访问的页码
        current_page = request.GET.get("page")
        page_info = PageInfo(current_page,all_count,10,"/custom",11)
    
        user_list = models.User_info.objects.all()[page_info.start():page_info.end()]
    
        return render(request,"custom.html",{"user_list":user_list,"page_info":page_info})
    View.py
    class PageInfo(object):
    
        def __init__(self,current_page,all_count,per_page,base_url,show_page=11):
    
            #如果传值错误进入第一页
            try:
                self.current_page = int(current_page)
            except Exception as e:
                self.current_page = 1
            self.per_page = per_page            #每页显示的个数
    
    
            a,b = divmod(all_count,per_page)    #页数  余数
            if b:
                a = a + 1
            self.all_page = a                   #总页码
            self.show_page = show_page
            self.base_url = base_url
    
        def start(self):
            # 1  0: 10
            # 2  10:20
            # 3  20:30
            return (self.current_page-1) * self.per_page
    
        def end(self):
            return self.current_page * self.per_page
    
        def pager(self):
    
            page_list = []
    
            half = int((self.show_page-1)/2)
    
            if self.all_page < self.show_page:
                begin = 1
                stop = self.all_page + 1
            else:
                if self.current_page < half:
                    begin = 1
                    stop = self.show_page + 1
                else:
                    if self.current_page + half > self.all_page:
                        begin = self.all_page - 10 +1
                        stop = self.all_page + 1
                    else:
                        begin = self.current_page - half
                        stop = self.current_page + half +1
    
            if self.current_page <=1:
                prev = "<li><a href='#'>上一页</a></li>"
            else:
                prev = "<li><a href='%s/?page=%s'>上一页</a></li>"%(self.base_url,self.current_page - 1)
    
            page_list.append(prev)
    
    
    
            for i in range(begin,stop):
                if i ==  self.current_page:
                    temp = "<li class='active'><a href='/custom/?page=%s'>%s</a></li>"%(i,i)
                else:
                    temp = "<li><a href='%s/?page=%s'>%s</a></li>"%(self.base_url,i,i)
                page_list.append(temp)
    
    
            if self.current_page >= self.all_page:
                nex = "<li><a href='#'>下一页</a></li>"
            else:
                nex = "<li><a href='%s/?page=%s'>下一页</a></li>" % (self.base_url,self.current_page + 1)
    
            page_list.append(nex)
    
            return "".join(page_list)
    utils/pager.py
    from django.db import models
    
    # Create your models here.
    
    
    class User_type(models.Model):
        uid = models.BigAutoField(primary_key=True)
        title = models.CharField(max_length=32)
    
    class User_info(models.Model):
        name = models.CharField(max_length=32)
        age = models.CharField(max_length=32)
        ut = models.ForeignKey("User_type")
    models.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" />
    </head>
    <body>
    
        {% for row in user_list %}
            <li>{{ row.name }}</li>
        {% endfor %}
    
    
        <nav aria-label="Page navigation">
          <ul class="pagination">
            {{ page_info.pager |safe }}
    
          </ul>
        </nav>
    </body>
    </html>
    custom.html
    class PageInfo(object):
    
        def __init__(self,current_page,all_count,per_page,base_url,show_page=11):
    
            #如果传值错误进入第一页
            try:
                self.current_page = int(current_page)
            except Exception as e:
                self.current_page = 1
            self.per_page = per_page            #每页显示的个数
    
    
            a,b = divmod(all_count,per_page)    #页数  余数
            if b:
                a = a + 1
            self.all_page = a                   #总页码
            self.show_page = show_page
            self.base_url = base_url
    
        def start(self):
            # 1  0: 10
            # 2  10:20
            # 3  20:30
            return (self.current_page-1) * self.per_page
    
        def end(self):
            return self.current_page * self.per_page
    
        def pager(self):
    
            page_list = []
    
            half = int((self.show_page-1)/2)
    
            if self.all_page < self.show_page:
                begin = 1
                stop = self.all_page + 1
            else:
                if self.current_page < half:
                    begin = 1
                    stop = self.show_page + 1
                else:
                    if self.current_page + half > self.all_page:
                        begin = self.all_page - 10 +1
                        stop = self.all_page + 1
                    else:
                        begin = self.current_page - half
                        stop = self.current_page + half +1
    
            if self.current_page <=1:
                prev = "<li><a href='#'>上一页</a></li>"
            else:
                prev = "<li><a href='%s?page=%s'>上一页</a></li>"%(self.base_url,self.current_page - 1)
    
            page_list.append(prev)
    
    
    
            for i in range(begin,stop):
                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_list.append(temp)
    
    
            if self.current_page >= self.all_page:
                nex = "<li><a href='#'>下一页</a></li>"
            else:
                nex = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url,self.current_page + 1)
    
            page_list.append(nex)
    
            return "".join(page_list)
    修改后 utils/pager.py

    五. XSS

    对用户提交的数据验证
    
    1.以安全的字符串显示出来,没有样式
    2.加safe,以安全的方式显示,过滤关键字

    六. CSRF

    CSRF(Cross-site request forgery)跨站请求伪造,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS)
        但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。
    
    自己理解:csrf_token防止从别的网站向自己网站发post请求, 客户来访问网站,网站会向客户发送随机字符串,然后客户带随机字符串发送post请求
            只有带随机字符串来,网站才认,一般是post请求才要求带随机字符串,其它网站第一次来不会带随机字符串。

    a. django开启csrf 

    MIDDLEWARE = [
        'django.middleware.csrf.CsrfViewMiddleware',
    ]
    

    b.HTML中使用

    {% csrf_token %}       #只要写上{% csrf_token %} 会有一个隐藏的input随机字符串,在cookie也有一个随机的字符串,form表单提交数据时,一般会使用
    {{ csrf_token }}       #生成随机的字符串

    c.django中设置防跨站请求伪造功能有分为全局和局部

    #局部
    
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    
    @csrf_protect   settings中没有设置全局中间件,为当前函数强制设置防跨站请求伪造功能。
    @csrf_exempt    settings中设置了全局中间件,取消当前函数防跨站请求伪造功能。
    
    #fbv
    
    @csrf_protect
    def func(object):
        pass
    
    #cbv
    
    from django.views import View
    from django.utils.decorators import method_decorator
    
    @method_decorator(csrf_exempt,name="dispatch")
    class foo(View)
        pass
    fbv和cbv应用装饰器  
    #方式一 类上加装饰器:
    
    def wrapper(func):
        def inner(*args,**kwargs):
            return func(*args,**kwargs)
        return inner
    
    @method_decorator(wrapper,name="get")
    @method_decorator(wrapper,name="post")
    class foo(View):
    
        def get(self,request):
            pass
    
        def post(self,request):
            pass
    
    
    
    #方式二 类上“dispatch”加装饰器:
    
    def wrapper(func):
        def inner(*args,**kwargs):
            return func(*args,**kwargs)
        return inner
    
    @method_decorator(wrapper,name="dispatch")
    class foo(View):
    
        def dispatch(self,request,*args,**kwargs):
            return xxx
    
        def get(self,request):
            pass
    
        def post(self,request):
            pass
    
    
    #方式三 方法上加装饰器:
    
    def wrapper(func):
        def inner(*args,**kwargs):
            return func(*args,**kwargs)
        return inner
    
    class foo(View):
    
    
        @method_decorator(wrapper)
        def get(self,request):
            pass
    
        def post(self,request):
            pass
    cbv应用其它装饰器

    d. Ajax提交数据 携带CSRF 

    1. 通过获取隐藏的input标签中的字符串 放置在data中发送  js代码可以和html在不同文件中(推荐使用)

    {% csrf_token %}
    
    $.ajax({
    	data:{"csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()
    });
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form method="POST" action="/csrf1.html">
            {% csrf_token %}
            <input id="user" type="text" name="user"/>
            <a onclick="submitForm();">Ajax提交</a>
        </form>
    
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function submitForm() {
                var csrf = $('input[name="csrfmiddlewaretoken"]').val();
                var user = $("#user").val();
                $.ajax({
                    url:'/csrf1.html',
                    type:'POST',
                    data:{"user":user,"csrfmiddlewaretoken":csrf},
                    success:function (arg) {
                        console.log(arg);
                    }
    
                })
            }
        </script>
    
    
    
    </body>
    </html>
    csrf1.html
    urlpatterns = [
    
        url(r'^csrf1.html', views.csrf1),
    ]
    urls.py
    def csrf1(request):
    
        if request.method == 'GET':
            return render(request,'csrf1.html')
        else:
            return HttpResponse('ok')
    View.py

    2. 通过获取返回的cookie中的字符串 放置在请求头中发送 

    通过在console中 document.cookie可以获取csrftoken=JPv1gIdrBiAlK2RCrgFs0OKwsncPXvwPfMhEWIVzMdMFymIayiuGu2GkBAu57moL
    但需要切割字符串,通过引入jquery.cookie.js对cookie操作,使用$.cookie("csrftoken")
    
    <script src="/static/jquery.cookie.js"></script>
    
    $.ajax({
    	headers:{"X-CSRFToken":$.cookie('csrftoken')},
    })
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form method="POST" action="/csrf1.html">
            {% csrf_token %}
            <input id="user" type="text" name="user"/>
            <a onclick="submitForm();">Ajax提交</a>
        </form>
    
        <script src="/static/jquery-1.12.4.js"></script>
        <script src="/static/jquery.cookie.js"></script>
        <script>
            function submitForm() {
                var token = $.cookie("csrftoken");
                var user = $("#user").val();
                $.ajax({
                    url:'/csrf1.html',
                    type:'POST',
                    headers:{"X-CSRFToken":token},
                    data:{"user":user},
                    success:function (arg) {
                        console.log(arg);
                    }
    
                })
            }
        </script>
    
    
    
    
    
    </body>
    </html>
    csrf1.html

    3. 直接在ajax里发送

    模版页面第一次render渲染时生成,js代码需要和html在一个文件中。如果js代码在其它文件中,是不会渲染的
    
    $.ajaxSetup({
        data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
    });
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form method="POST" action="/csrf1.html">
    
            <input id="user" type="text" name="user"/>
            <a onclick="submitForm();">Ajax提交</a>
        </form>
    
        <script src="/static/jquery-3.2.1.js"></script>
        <script>
            function submitForm() {
    
                var user = $("#user").val();
                $.ajax({
                    url:'/index/',
                    type:'POST',
                    data:{"user":user,"csrfmiddlewaretoken":"{{ csrf_token }}"},
                    success:function (arg) {
                        console.log(arg);
                    }
    
                })
            }
        </script>
    
    
    
    </body>
    </html>
    csrf1.html

    七. 中间件

    #django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
    

    a. 注册中间件

    在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。
    
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        "md.M1",
        "md.M2",
    ]
    

      

      

      

     

      

     

     

     

      

     

     

      

      

  • 相关阅读:
    Oracle存储过程编译卡死的解决方法
    异常来自 HRESULT:0x800A01A8
    WIP
    R12: How to add Microsoft Excel as Type to the Create Template List of Values in BI Publisher (Doc ID 1343225.1)
    XML Publisher Template Type
    打印报表以显示具有给定责任的用户-FNDSCRUR责任用户
    Credit Memo和Debit Memo在AR以及AP中的概念比较
    EBS-BG&LE&OU
    普通pc电脑安装苹果系统mac_详细教程(精)附带所有工具下载
    教程 打造OS X Mavericks原版 EFI Clover 引导安装
  • 原文地址:https://www.cnblogs.com/golangav/p/7077090.html
Copyright © 2020-2023  润新知