s4 django


# web框架本质

    - 参考博客
        https://www.cnblogs.com/wupeiqi/articles/5237672.html

        import socket
        sock = socket.socket()
        sock.bind(('127.0.0.1',8080))
        sock.listen(5)
        while True:
            conn,addr = sock.accept() # hang住
            # 有人来连接了
            # 获取用户发送的数据
            data = conn.recv(8096)
            conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
            conn.send(b'123123')
            conn.close()

    1. Http,无状态,短连接
    2.
        浏览器(socket客户端)
        网站(socket服务端)
        
    3. 自己写网站
        a. socket服务端
        b. 根据URL不同返回不同的内容
            路由系统:
                URL -> 函数
        c. 字符串返回给用户
            模板引擎渲染:
                HTML充当模板(特殊字符)
                自己创造任意数据
            字符串
            
    4. Web框架:
        框架种类:
            - a,b,c                     --> Tornado
            - [第三方a],b,c          --> wsgiref -> Django
            - [第三方a],b,[第三方c]  --> flask + jinja2
            
        分类:
            - Django框架
            - 其他        

- 基本配置

    pip3 install django
    
    命令:
        # 创建Django程序
        django-admin startproject mysite
        # 进入程序目录
        cd mysite
        # 启动socket服务端,等待用户发送请求
        python manage.py runserver 127.0.0.1:8080

    pycharm:
        ...
        
    Django程序目录:
        mysite
            mysite
                - settings.py  # Django配置文件
                - url.py       # 路由系统:url->函数
                - wsgi.py      # 用于定义Django用socket, wsgiref,uwsgi
        
            # 对当前Django程序所有操作可以基于 python manage.py runserver
            manage.py

            
    # Django目录介绍
    
        django-admin startproject mysite
        cd mysite
        python manage.py starapp app01
        
        project
            - app01
                - admin   Django自带后台管理相关配置
                - modal   写类,根据类创建数据库表
                - test    单元测试
                - views   业务处理,多时可创建目录
            - app02
            - app03    

    1. 创建project
    2. 配置:
        - 模板路径
            template目录
            
            TEMPLATES = [
                {
                    'BACKEND': 'django.template.backends.django.DjangoTemplates',
                    'DIRS': [os.path.join(BASE_DIR, 'template')],
                    'APP_DIRS': True,
                    'OPTIONS': {
                        'context_processors': [
                            'django.template.context_processors.debug',
                            'django.template.context_processors.request',
                            'django.contrib.auth.context_processors.auth',
                            'django.contrib.messages.context_processors.messages',
                        ],
                    },
                },
            ]
        - 静态文件路径
            static目录
            
            STATIC_URL = '/static/'
            STATICFILES_DIRS = (
                os.path.join(BASE_DIR,'static'),
            )

    3. 额外配置
        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',
        ]

    4.url对应关系
        /login/ login
        
        from django.shortcuts import render,redirect,HttpResponse
        
        def login(request):
            request.method
            request.POST    --> 请求体
            request.GET      --> 请求头URL
            request.POST.getlist('多选下拉框')
            
        return HttprResponse(‘字符串’)
        return render(request,'xx/login.html',{...})
        return redirect('/url/')
        # return render(request,'xx/login.html',{...})
        # \template\xx\login.html    
            
        get请求:只有request.GET
        post请求:request.GET和request.POST都可能有值
    
    5.模板引擎中的特殊标志
    
        login.html
            {{name}}
        def login(request):
            return render(request,'login.html',{'name':'alex'})
            
            
        def index(request):
            # return HttpResponse('index')
            return render(request,
                          'index.html',
                          {'name':'alex',
                           'users':['abc','def'],
                           'user_dict':{'k1':'v1','k2':'v2'},
                           'user_list_dict':[
                               {'id':1,'name':'alex','email':'alex3714@163.com'} ,
                               {'id':2,'name':'alex2','email':'alex3714@1632.com'} ,
                               {'id':3,'name':'alex3','email':'alex3714@1633.com'} ,
                           ]
                           })

        <h1>模板标记的学习</h1>
        <p>{{ name }}</p>
        <p>{{ users.0}}</p>
        <p>{{ users.1}}</p>
        <p>{{ user_dict.k1}}</p>
        <p>{{ user_dict.k2}}</p>
        <h1>循环</h1>
        <ul>
        {% for item in users %}
            <li>{{ item }}</li>
        {% endfor %}
        </ul>
        <table border="1">
        {% for row in user_list_dict %}
            <tr>
                <td>{{ row.id }}</td>
                <td>{{ row.name }}</td>
                <td>{{ row.email }}</td>
                <td><a>编辑</a>|<a href="/del/?nid={{ row.id }}">删除</a></td>
            </tr>
        {% endfor %}
        </table>
        
        {%if 1>2 %}
        ...    
        {%endif%}
        
        
    # Ajax
    
        # jQuery
        $.ajax({
            url: '要提交的地址',
            type: 'POST', // GET或POST,提交方式
            data: {'k1':[1,2,3,4],'k2':JSON.stringify({'k1':v1,...})}, // 提交的数据
            dataType: 'JSON',// arg的数据格式
            traditional: true,// 如果提交的数据的值有列表,则需要添加此属性
            success:function(data){
                // 当前服务端处理完毕后,自动执行的回调函数
                // data返回的数据
                location.href = "要跳转的地址"
            }
        })
    
    # 其他:
    
        - Form表单提交,页面会刷新
        - Ajax提交页面不刷新
        - 使用时机:
            模态对话框(Ajax)
                - 少量输入框
                - 数据少
                - 登录
            新URL方式
                - 操作多
                - 对于大量的数据以及操作


        - js阻止默认事件的发生
        
            onclick=‘return modelEdit();’
            
            function modelEdit(){
                alert(123);
                return false;
                // return true;
            }
            
        - jQuery 事件阻止默认事件发生
            $('#addmodal').click(function(){
                return false;
            })    
        
    # 插件
        - bootstrap
            - 看图拷贝 *
            - 常用标签
            - 样式
            1. 响应式布局: @media()
            2. 栅格:    
            3. 表格
            4. 导航条
            5. 路径导航
                    
        - fontawesome
        
        # 当鼠标移动到xx样式的标签上时,其子标签.g应用以下属性
            .xx:hover .g{        
        

    # 后台管理页面示例


    
- Cookie

    # 使用:每页显示多少条

    a. 保存在浏览器端“键值对”
    b. 服务端可以向用户浏览器端写cookie
    c. 客户端每次方请求时,会携带cookie去    
    
        
    - 发送Http请求时,在请求头中携带当前所有可访问的cookie
    - 响应头
                   
        @xzxx
        def index(request):
        
            obj = HttpResponse('...')
            obj.set_cookie(.....)
            request.COOKIES.get(...)
            
            
            obj.set_signed_cookie(.....)
            request.get_signed_cookie(....)    
    
        def classes(request):
            # 去请求的cookie中找凭证
            # print(request.COOKIES)
            # 打印所有cookie
            
            tk = request.COOKIES.get('ticket')
            
            # tk = request.get_signed_cookie('ticket',salt='jjjjjj')
            
            if not tk:
                return redirect('/login/')
        
        def login(request):
            ...
            obj = redirect('/classes/')
            # obj = HttpResponse('ok')
            # obj = redirect(..)
            # obj.set_cookie('ticket','sssssdfdfdfd')
            # obj.set_cookie('ticket',"asdasdsd",max_age=10)
            
            # import datetime
            # from datetime import timedelta
            # ct = datetime.datetime.utcnow()
            # v= timedelta(seconds=10)
            # value = ct + v
            # obj.set_cookie('ticket',"asdasdsd",expires=value)
            
            obj.set_signed_cookie('ticket',"123123",salt='jjjjjj')
            
            return obj
            
    
            
    set_cookie参数
        key,
        value='',
        max_age=None,         # 超时值
        expires=None,         # 具体超时日期
        path='/',            # 路径
        domain=None,         # 域名 sso统一用户登陆使用
        secure=False,       # Https使用
        httponly=False      # 只能自Http请求中传入,js代码无法获取到(相对)
    
    cookie签名:
        obj.set_signed_cookie('ticket',"123123",salt='jjjjjj')
        
    自定义cookie签名
    
        # settings.py
        SIGNING_BACKEND = "c1.MySigner"
        
        # project/c1.py
        
        from django.core.signing import TimestampSigner
        class MySigner(TimestampSigner):

            def sign(self, value):
                return value+'123123123'

            def unsign(self, value, max_age=None):
                v = value[0:-8]
                return v        
    
    # 装饰器实现登陆    
    
    

    
    
# MVC,MTV
    
    models(数据库,模型)   views(html模板)    controllers(业务逻辑处理)    --> MVC

    models(数据库,模型)   templates(html模板)  views(业务逻辑处理)          --> MTV
    
    Django -> MTV    

    
        
- 路由系统

    url -> 函数
    
    a. /login/ -> def login
    
    b. /add-user/(\d+)/          ->  def add_user(request,a1)
      /add-user/(\d+)/(\d+)/        ->  def add_user(request,a1,a2)
    
    c. /add-user/(?P<a1>\d+)/    ->  def add_user(request,a1)
    
        终止符:
            ^edit$
        伪静态
            url(r'^edit/(\w+).html$', views.edit),
                
        # SEO
    
    d. 路由分发
        from django.conf.urls import url,include
        urls.py
            url(r'^app01/', include('app01.urls')),
        
        app01.urls.py
            url(r'^index.html$', views.index),
            
    # 默认页面
        # url(r'^', default),
        
        from django.shortcuts import HttpResponse
        def default(request):
            return HttpResponse('something wrong')            
        
            
    e. 别名
        
        /add-user/(\d+)/  ->  def add_user(request,a1)  name=n1
        
        根据名称可以反向生成URL
        1. 在Python代码中
            from django.urls import reverse
            # v =  reverse('n1',args = (451,))        # add-user/(\d+)/
            v = reverse('n1',kwargs={'a1':1111})    # /add-user/(?P<a1>\d+)/
            print(v)
            # /index/451/
            
        2. 模板语言中:
            url(r'^login/', views.login,name='m1')
            {% url "m1" %}
            {% url "m1" i %}
                    
            {% for i in user_list %}
                <li>{{ i }} | <a href="/edit/{{ i }}/"> 编辑</a></li>
                <li>{{ i }} | <a href="{% url 'n2' i 1%}"> 编辑</a></li>
            {% endfor %}
            
    # 别名用于做权限
        
        使用一:
        
            def index(request):
                url_list = [
                    'n1',
                    'n2',
                    'n3',
                ]
            return render(...,url_list)
                
            html:
            <ul>
                for v in url_list:
                    <li> <a href='{% url v %}'>ff</a> </li>
            </ul>
        
        使用二:
        
            def index(request):
                url_list = [
                    'n1',
                    'n2',
                    'n3',
                ]
            temp = []
            for i in url_list:
                url = reverse(i)
                temp.append(url)
                
            return render(...,temp)    

            html:
            <ul>
                for url in temp:
                    <li> <a href='{{url}}'>ff</a> </li>
            </ul>


            
- 视图函数

    - CBV & FBV    
    
        # get 查,post 创建,put 更新,delete 删除 等  -----ajax方式下
        # form表单只 post、get        
        
        # urls.py
        
            from app01 import views
            urlpatterns = [
                url(r'^login.html$',views.Login.as_vies())
            ]
        
        #views.py
        
            from django.views import View
            class Login(View):
                # get    查
                # post   创建
                # put    更新
                # delete 删除
                def get(self,request):
                    # return  HttpResponse('login.get')
                    return render(request,'login.html')
                
                def post(self,request):
                    print(request.POST.get('user'))
                    return HttpResponse('Login.post')
            
    - 自定义dispatch:
        
        from django.views import View
        class Login(View):
            # get 查,post 创建,put 更新,delete 删除 等  -----ajax方式下
            # form表单只 post、get
            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  HttpResponse('login.get')
                return  render(request,'login.html')
            def post(self,request):
                print(request.POST.get('user'))
                return HttpResponse('login.post')

                
    - CBV中添加装饰器
    
        def wrapper(func):
            def inner(*args,**kwargs):
                return func(*args,**kwargs)
            return inner
        1. 指定方法上添加装饰器

            # class Foo(View):
            #
            #     @method_decorator(wrapper)
            #     def get(self,request):
            #         pass
            
            #     @method_decorator(wrapper)
            #     def post(self,request):
            #         pass
            
        2. 在类上添加
        
            #     @method_decorator(wrapper,name='dispatch')
            #     @method_decorator(wrapper,name='get')     # get方式
            #     class Foo(View):
            #
            #         def get(self,request):
            #             pass
            #
            #         def post(self,request):
            #             pass
                
- 分页

    - 分批获取数据
        models.UserInfo.objects.all()[0:10]
        models.UserInfo.objects.all()[10:20]

    - django 自带
        适用于:只有上一页,下一页
        # views.py
        
            def index(request):
                # for i in range(300):
                #     name='root'+str(i)
                #     models.UserInfo.objects.create(name=name,age=18,ut_id=1)
                from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage

                current_page=request.GET.get('page')

                user_list=models.UserInfo.objects.all()
                paginator=Paginator(user_list,10)
                # per_page;每页条目
                # count 数据总个数
                # num_page 总页数
                # page_range 总页数的索引范围
                # page: page对象
                try:
                    posts =paginator.page(current_page)
                except PageNotAnInteger as e:
                    posts =paginator.page(1)
                except EmptyPage as e:
                    posts =paginator.page(1)
                # has_next 是否有下一页
                # next_page_number 下一页页码
                # has_previous 是否有上一页
                # previous_page_num 上一页页码
                # object_list 分页后的数据列表
                # number 当前页
                # paginator 对象

                return render(request,'index.html',{'posts':posts})    

        # html
        
            <h1>用户列表</h1>
            <ul>
                {% for row in posts.object_list %}
                    <li>{{ row.name }}</li>
                {% endfor %}
            </ul>
            
            <div>
                {% if posts.has_next %}
                    <a href="/index.html?page={{ posts.next_page_number }}">下一页</a>
                {% endif %}

                <!--
                {% for num in posts.paginator.page_range %}
                    <a href="/index.html?page={{ num }}">{{ num }}</a>
                {% endfor %}
                -->

                {% if posts.has_previous %}
                    <a href="/index.html?page={{ posts.previous_page_number }}">上一页</a>
                {% endif %}
            </div>    

            
    - 自定义分页组件


- 模板

    - 基本使用
    
    - 母版继承
    
        母版:
            <html>
                ...
                {% block s1 %} {%endblock%} # 占位
                ...
                {% block s2 %} {%endblock%}
            
            </html>
            
        子板:
            {% extends "layout.html "%}
            
            {% block s1 %} <h1>fff</h1> {%endblock%}
            {% block s2 %} <h1>ffffff</h1> {%endblock%}

    - include
    
        导入小组件
        # pub.html
            <div>
                <h3>特别漂亮的组件</h3>
                <div class="title">标题:{{ name }}</div>
                <div class="content">内容:{{ name }}</div>
            </div>            
        # html中:
            {% include 'pub.html' %}
            
    - 函数-> 自动执行
    
    - 模板自定义函数:
        - simple_filter
            - 最多两个参数,方式: {{第一个参数|函数名称:"第二个参数"}}
            - 可以做条件判断
        - simple_tag
            - 无限制: {% 函数名 参数 参数%}            

    -自定义simple_tag步骤:
    
        a、在app中创建templatetags模块
        
        b、创建任意 .py 文件,如:xx.py
        
            from django import template
               
            register = template.Library()
              
            @register.filter
            # filter 可作为条件语句判断,而simple_tag 不能
            def my_upper(value,arg)
                return value + argh
              
            @register.simple_tag
            def my_simple_time(v1,v2,v3):
                return  v1 + v2 + v3
                
        c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
            {% load xx %}
            
            
        d、使用simple_tag
        
            {{name|my_upper:"xxx"}}  #filter
                {% if name|my bool %}
                {% else %}
                {% endif %}
            
            {% my_simple_time 1 2 3%}
            {% my_input 'id_username' 'hide'%}

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

    - 例子:
    
        # html

            <h1>filter</h1>
                {{ name|my_upper:'666' }}
                {% if name|my_bool %}
                    <h3>true</h3>
                {% else %}
                    <h3>false</h3>
                {% endif %}

            <h2>tag</h2>
                {% my_lower 'ALEX' 'x' 'sb' 'dddd'%}

        # xx.py
        
            from django import template

            register =template.Library()

            @register.filter
            def my_upper(value,arg):
                return value+arg

            @register.filter
            def my_bool(value):
                return False

            @register.simple_tag
            def my_lower(value,a1,a2,a3):
              return value+a1+a2+a3
              
                                    
                                        
- xss攻击

    # 跨站脚本攻击
    
    - 慎用 safe和mark_safe
    - 非要用,一定要过滤关键字    
    - 后台:
        from django.utils.safestring import mark_safe
        newtemp = mark_safe(temp)
    - 前端:
        {{temp|safe}}

        
        
- CSRF/XSRF

    # 跨站请求伪造
    
    a. 基本应用
        form表单中添加
        {% csrf_token %}
        
        {{csrf_token}}    
        # 仅显示字符串
        # django默认在cookie中生成csrftoken
        
    
    b. 全站禁用
    
        # 'django.middleware.csrf.CsrfViewMiddleware',
    
    c. 局部禁用
    
        'django.middleware.csrf.CsrfViewMiddleware',
        
        from django.views.decorators.csrf import csrf_exempt

        @csrf_exempt
        def csrf1(request):

            if request.method == 'GET':
                return render(request,'csrf1.html')
            else:
                return HttpResponse('ok')
                
    d. 局部使用
    
        # 'django.middleware.csrf.CsrfViewMiddleware',
        
        from django.views.decorators.csrf import csrf_exempt,csrf_protect

        @csrf_protect
        def csrf1(request):

            if request.method == 'GET':
                return render(request,'csrf1.html')
            else:
                return HttpResponse('ok')
    
    c. 特殊CBV
    
        from django.views import View
        from django.utils.decorators import method_decorator
        
        @method_decorator(csrf_protect,name='dispatch')    # 只能加在类上面
        class Foo(View):
            
            def get(self,request):
                pass

            def post(self,request):
                pass
    


    - Ajax提交数据时,携带CSRF
        
        方法一:放置在data中携带
                
            <form action="/csrf1.html" method="POST" >
                {% csrf_token %}
                <input id='user'type="text" name="user">
                <input type="submit" value="提交">
                <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>
            
            
        方法二:放在请求头中
        
        
            <form action="/csrf1.html" method="POST" >
                {% csrf_token %}
                <input id='user'type="text" name="user">
                <input type="submit" value="提交">
                <a onclick="submitForm()">ajax提交</a>
            </form>
            
            <script src="/static/jquery-1.12.4.js"></script>
            <script src="/static/jquery.cookie.js"></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);
                    }
                })
            }
            
            
            # 插件:
                jquery.cookie.js
                
            # 获取:
                $.cookie('csrftoken')
                
            # 设置
                $.cookie('dfdfdfdfdf','234324234324234')

- admin

    python manage.py createsuperuser
    
    # app01/admin.py
    
        from django.contrib import admin
        from app01 import models
        # Register your models here.
        admin.site.register(models.UserInfo)
        

                
- Session


    - cookie是什么?
        保存在客户端浏览器上的键值对
        
    - session是什么?
        保存在服务器端的数据(本质是键值对)
            {
                ‘sdsfefefefe’:{'id':1,'name':'yuhao',email='xxx'}
                ‘eerererfefe’:{'id':1,'name':'yuhao2',email='xxx'}
            }
        # session依赖cookie
        # 作用:保持会话 web网站
        # 好处:敏感信息不会直接给客户
        
        # 默认在数据库
        # 大型放在缓存
    
    - 梳理:
    
        1.保存在服务器端的数据(本质是键值对)
        2.配置文件中
            -存储位置
            -超时时间、每次刷新更新时间
        3.request.session
            -增删改
            -获取随机字符串
            -主动设置超时时间
            
    - django中的使用:

        obj =models.UserAdmin.objects.filter(username=u,password=p).first()
        if obj:
            request.session['username']=obj.username
            return redirect('/index/')
        
        v=request.session.get('username')
        if v:
            return HttpResponse('sucessfull,welcome %s'%v)
        else:
            return redirect('/login/')    

            
    - django 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失效策略。
    
    - Session用户验证    
                
        def login(func):
            def wrap(request, *args, **kwargs):
                # 如果未登陆,跳转到指定页面
                if request.path == '/test/':
                    return redirect('http://www.baidu.com')
                return func(request, *args, **kwargs)
            return wrap
            
    - Django提供了5种类型的Session供开发者使用:

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


- 中间件

    1. Django请求生命周期
        请求 -> WSGI -> 中间件 -> url -> 视图...
        
    2. Django使用的WSGI的服务:
        测试用:wsgiref
        生产用:uwsgi
        
    3. Wsgi+Django
        from wsgiref.simple_server import make_server
          
        def RunServer(environ, start_response):

            Django框架开始
            中间件
            路由系统
            视图函数
            。。。。。
            
            start_response('200 OK', [('Content-Type', 'text/html')])    
            return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
        
        if __name__ == '__main__':
            httpd = make_server('127.0.0.1', 8000, RunServer)
            httpd.serve_forever()
            
    - 类
        process_request
        
        process_response(...response)
            必须有返回值
            return response
            
        process_view
        process_exception
        process_template_view
        
    - 注册中间件
    
        [
            ....
        ]
    
    - 应用:
    
        # 对所有请求或一部分请求做批量处理
        # 登陆验证
        # 缓存

    - 执行过程图    

    - 例子一:
    
        # settings.pymysql
        
            MIDDLEWARE = [
                ...
                'm1.Middle1',
                'm1.Middle2',
            ]
            
        # m1.py
            from django.utils.deprecation import MiddlewareMixin

            from django.shortcuts import HttpResponse
            class Middle1(MiddlewareMixin):
                def process_request(self, request):
                    print('m1.process_request')
                    # return HttpResponse('不要在往下周了')

                def process_response(self, request, response):
                    print('m1.process_response')
                    return response

            class Middle2(MiddlewareMixin):
                def process_request(self, request):
                    print('m2.process_request')
                    # return HttpResponse('不要在往下周了')

                def process_response(self, request, response):
                    print('m2.process_response')
                    return response    
                
    - 例子二:
    
        # project\md.py
            from django.utils.deprecation import MiddlewareMixin
            from django.shortcuts import HttpResponse
            class M1(MiddlewareMixin):
                def process_request(self,request):
                    print('m1.process_request')

                def process_view(self, request, callback, callback_args, callback_kwargs):
                    print('m1.process_view')
                    # response = callback(request,*callback_args,**callback_kwargs)
                    # return response

                def process_response(self,request,response):
                    print('m1.process_response')
                    return response

                def process_exception(self, request, exception):
                    print('m1.process_exception')

                def process_template_response(self,request,response):
                    """
                    视图函数的返回值中,如果有render方法,才被调用
                    :param request:
                    :param response:
                    :return:
                    """
                    print('m1.process_template_response')
                    return response

            class M2(MiddlewareMixin):
                def process_request(self,request):
                    print('m2.process_request')
                def process_view(self, request, callback, callback_args, callback_kwargs):
                    print('m2.process_view')
                def process_response(self,request,response):
                    print('m2.process_response')
                    return response
                def process_exception(self, request, exception):
                    print('m2.process_exception')
                    return HttpResponse('错误了...')
                    
        # app01\views.py
        
            class JSONResponse:
            # 封装JSON功能
                def __init__(self,req,status,msg):
                    self.req = req
                    self.status = status
                    self.msg = msg
                def render(self):
                    import json
                    ret = {
                        'status': self.status,
                        'msg':self.msg
                    }
                    return HttpResponse(json.dumps(ret))

            def test(request):
                # print('test')
                # return HttpResponse('...')
                ret = {}
                return JSONResponse(request,True,"错误信息")
            


            

- AJAX全套
    Ajax博客:
        http://www.cnblogs.com/wupeiqi/articles/5703697.html

    1. Ajax,
        a. XMLHttpRequest
            
            GET请求:
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        alert(xhr.responseText);
                    }
                };
                xhr.open('GET','/add2/?i1=12&i2=19');
                xhr.send();
            
            
            POST请求:
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        alert(xhr.responseText);
                    }
                };
                xhr.open('POST','/add2/');
                xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                xhr.send("i1=12&i2=19");
        
        
        b. jQuery Ajax
            # 内部基于“原生Ajax”
                    $.ajax({
                        url:'/add1/',
                        type:"POST",
                        data:{'i1':$('#i1').val(),'i2':$('#i2').val()},
                        success:function(arg){
                            $('#i3').val(arg);
                        }
                    })

    2. 伪Ajax,非XMLHttpRequest
        技术:
            iframe标签,不刷新发送HTTP请求
            <div>
                <input type="text"id="txt1">
                <input type="button"value="查看"onclick="changeSrc();">
            </div>
            <iframe id="ifr" src="http://www.baidu.com" frameborder="0" style="width: 1000px;height:2000px;"></iframe>

            <script>
                function changeSrc(){
                    var inp =document.getElementById('txt1').value;
                    document.getElementById('ifr').src=inp
                }
            </script>
        
        示例:
            <form id="f1" method="POST" action="/fake_ajax/" target="ifr">
                <iframe id="ifr" name="ifr" style="display: none"></iframe>
                <input type="text" name="user" />
                <a onclick="submitForm();">提交</a>
            </form>

            <script>
                function submitForm(){
                    document.getElementById('ifr').onload = loadIframe;
                    document.getElementById('f1').submit();

                }
                function loadIframe(){
                    var content = document.getElementById('ifr').contentWindow.document.body.innerText;
                    alert(content);
                }
            </script>
            
    3. 基于Ajax上传文件:
    
        1. XMLHttpRequest
            - 原生: FormData
            - jQuery: FormData
            
        2. 伪造
            - 兼容性

        3. 总结:
            1. 上传文件
                伪造
            2. 数据
                - jQuery
                - XMLHttpRequest(伪造)
                
            3. 不要被好看的上传按钮迷惑
            
    4. 文件上传示例代码:

        <body>
            <h1>原生Ajax上传文件</h1>
            <input type="file"id="i1">
            <a onclick="upload1();">上传</a>
            <div id="container1"></div>

            <h1>jQuery Ajax上传文件</h1>
            <input type="file"id="i2">
            <a onclick="upload2();">上传</a>
            <div id="container2"></div>

            <h1>伪Ajax上传文件</h1>
            <form id ='f1'action="/upload/"method="POST" target="ifr"enctype="multipart/form-data">
                <iframe id="ifr" name="ifr"  style="display:none"></iframe>
                <input type="file"name="fafafa">
                <a href="#" onclick="upload3();">上传</a>
            </form>
        <div id="container3"></div>

        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function upload1(){
                var formData = new FormData();
                // 原生上传依赖FormData
                // 不用加 setRequestHeader
                formData.append('k1','v1');
                formData.append('fafafa',document.getElementById('i1').files[0]);

                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        var file_path =xhr.responseText;
                        var tag=document.createElement('img');
                        tag.src ='/'+file_path;
                        document.getElementById('container1').appendChild(tag);
                    }
                };
                xhr.open('POST','/upload/');
                xhr.send(formData);
            }

            function upload2(){
                var formData = new FormData();
                formData.append('k1','v1');
                // formData.append('fafafa',document.getElementById('i1').files[0]);
                formData.append('fafafa',$('#i2')[0].files[0]);
                // jQuery 和 Dom 转换
                // $('#i2') --> $('#i2')[0]
                // document.getElementById('i1') --> $(document.getElementById('i1'))
                $.ajax({
                    url:'/upload/',
                    type:'POST',
                    data:formData,
                    contentType:false,
                    processData:false,
                    success:function(arg){
                        var tag=document.createElement('img');
                        tag.src ='/'+arg;
                        $('#container2').append(tag)
                    }
                })
            }

            
            function upload3(){
                document.getElementById('ifr').onload=loadIframe;
                document.getElementById('f1').submit();
            }
            function loadIframe(){
                var content =document.getElementById('ifr').contentWindow.document.body.innerText;
                var tag=document.createElement('img');
                tag.src ='/'+content;
                $('#container3').append(tag)
            }
        </script>

        import os
        def upload(request):
            if request.method=='GET':
                return render(request,'upload.html')
            else:
                print(request.POST,request.FILES)
                file_obj =request.FILES.get('fafafa')
                file_path =os.path.join('static',file_obj.name)
                with open(file_path,'wb') as f:
                    for chunk in file_obj.chunks():
                        f.write(chunk)
                return HttpResponse(file_path)
                
    5. JSONP(跨域Ajax)
    
        武陪齐博客:
            www.cnblogs.com/wupeiqi/articles/5369773.html
            
        JSONP是一种方式,目的解决跨域问题    
        
        Ajax存在问题:
            访问自己域名URL
            访问其他域名URL - 被阻止
            
        浏览器的同源策略,
            - 禁止:Ajax跨域发送请求时,再回来时浏览器拒绝接受
            - 允许:script标签没禁止
            
        开发需求:向其他网站发Http请求
            - 浏览器->服务端->发送请求
            - 浏览器直接发送请求【考虑同源】
                1. 客户端
                    - URL?callback=xxxx
                    - function xxxx(arg){}
                    
                    
                2. 服务端
                    - 获取 funcname = request.GET.get(callback)
                    - 返回: funcname(....)        

        使用:
            1. 自己写动态创建script
                function getUsers(){
                     var tag = document.createElement('script');
                    tag.src = "http://www.s4.com:8001/users/?funcname=bbb?sdd";
                    document.head.appendChild(tag);
                 }
            2. jQuery
                $.ajax({
                    url: 'http://www.s4.com:8001/users/',
                    type: 'GET',
                    dataType: 'JSONP',
                    jsonp: 'funcname',
                    jsonpCallback: 'bbb'
                })

        其他:
            - 只能发GET请求
            - 约定    
            
        代码:
            <input type="button" value="获取用户列表" onclick="getUsers();">
            <ul id="user_list">
            
            </ul>
            <script src="/static/jquery-1.12.4.js"></script>
            <script>
                /*
               function getUsers(){
                   var xhr = new XMLHttpRequest();
                   xhr.onreadystatechange = function(){
                       if (xhr.readyState ==4){
                           var content= xhr.responseText;
                           console.log(content);
                       }
                   };
                   xhr.open('GET','http://www.s4.com:8001/users/');
                   xhr.send();
               }
               */
                /*
                function getUsers(){
                    var tag=document.createElement('script');
                    tag.src ='http://www.s4.com:8001/users/?funcname=bbb';
                    document.head.appendChild(tag);
                }
                function bbb(arg){
                    console.log(arg)
                }
                */
                function  getUsers(){
                    $.ajax({
                        url:'http://www.s4.com:8001/users/',
                        type:'GET',
                        dataType:'JSONP',
                        jsonp:'funcname',
                        jsonpCallback:'bbb'
                    })
                }
                function bbb(arg){
                        console.log(arg);
                }
            </script>
            
            from django.shortcuts import render,HttpResponse
            import json
            # Create your views here.
            def users(request):
                v=request.GET.get('funcname')
                print('requesting....')
                user_list= [
                    'alex','eric','egon'
                ]
                user_list_str =json.dumps(user_list)
                temp='%s(%s)' %(v,user_list,)
                return HttpResponse(temp)

    - CORS跨站资源共享
    
        返回值增加响应头
    
        简单请求:
            
            def new_users(request):
                obj = HttpResponse('返回内容')
                obj['Access-Control-Allow-Origin'] = "*"
                return obj
                
        复杂请求:
        
            def new_users(request):

                if request.method == "OPTIONS":
                    obj = HttpResponse()
                    obj['Access-Control-Allow-Origin'] = "*"
                    obj['Access-Control-Allow-Methods'] = "DELETE"
                    return obj

                obj = HttpResponse('asdfasdf')
                obj['Access-Control-Allow-Origin'] = "*"
                return obj
                
        - 可以发送任何请求                
                            
        代码:        
                
            <input type="button" value="获取用户列表" onclick="getUsers();">
            <ul id="user_list">
            
            </ul>

            <script src="/static/jquery-1.12.4.js"></script>
            <script>
                function getUsers(){
                    $.ajax({
                        url:'http://www.s4.com:8001/new_users/',
                        type:'GET',
                        success:function(arg){
                            console.log(arg);
                        }
                    })
                }
            </script>                
                    
                
            def new_users(request):
                user_list= [
                    'alex','eric','egon'
                ]
                user_list_str =json.dumps(user_list)
                obj=HttpResponse(user_list_str)
                obj['Access-Control-Allow-Origin']='*'
                return obj    
- 缓存

- 序列化

- 信号
               

posted @ 2020-01-18 21:00  badweather  阅读(139)  评论(0编辑  收藏  举报