s14 django其他

Django其他篇


- 参考博客
    Django高级:
        https://www.cnblogs.com/wupeiqi/articles/5246483.html

        
- ModelForm组件

    参考博客:
        http://www.cnblogs.com/wupeiqi/articles/6229414.html
    ModelForm(武sir博客)
        a.  class Meta:
                model,                           # 对应Model的
                fields=None,                     # 字段
                exclude=None,                    # 排除字段
                labels=None,                     # 提示信息
                help_texts=None,                 # 帮助提示信息
                widgets=None,                    # 自定义插件
                error_messages=None,             # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS)
                field_classes=None               # 自定义字段类 (也可以自定义字段)
                localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据
                如:
                    数据库中
                        2016-12-27 04:10:57
                    setting中的配置
                        TIME_ZONE = 'Asia/Shanghai'
                        USE_TZ = True
                    则显示:
                        2016-12-27 12:10:57
        b. 验证执行过程
            is_valid -> full_clean -> 钩子 -> 整体错误
    
        c. 字典字段验证
            def clean_字段名(self):
                # 可以抛出异常
                # from django.core.exceptions import ValidationError
                return "新值"
        d. 用于验证
            model_form_obj = XXOOModelForm()
            model_form_obj.is_valid()
            model_form_obj.errors.as_json()
            model_form_obj.clean()
            model_form_obj.cleaned_data
        e. 用于创建
            model_form_obj = XXOOModelForm(request.POST)
            #### 页面显示,并提交 #####
            # 默认保存多对多
                obj = form.save(commit=True)
            # 不做任何操作,内部定义 save_m2m(用于保存多对多)
                obj = form.save(commit=False)
                obj.save()      # 保存单表信息
                obj.save_m2m()  # 保存关联多对多信息
    
        f. 用于更新和初始化
            obj = model.tb.objects.get(id=1)
            model_form_obj = XXOOModelForm(request.POST,instance=obj)
            ...
    
            PS: 单纯初始化
                model_form_obj = XXOOModelForm(initial={...})

    - 要点:
        Model + Form => 验证 + 数据库操作
            - class LoginModelForm(xxxxx):
                 利用model.A中的字段
                
                
            1. 生成HTML标签:class Meta: ...
            2. mf = xxxModelForm(instance=ModelObj)
            3. 额外的标签, is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())
            4. 各种验证 is_valid() -> 各种钩子...
            5.     mf.save()
                # 或
                instance = mf.save(False)
                instance.save()
                mf.save_m2m()
    - 代码:
    
        # views.py

            url(r'^admin/', admin.site.urls),
            url(r'^index/', views.index),
            url(r'^user_list/', views.user_list),
            url(r'^edit-(\d+)/', views.user_edit),
            
        # model.py
        
            from django.db import models

            # Create your models here.
            class UserType(models.Model):
                caption = models.CharField(max_length=32)

            class UserGroup(models.Model):
                name = models.CharField(max_length=32)

            class UserInfo(models.Model):
                # username = models.CharField(verbose_name='用户',max_length=32)
                username = models.CharField(verbose_name='用户',max_length=32)
                email =models.EmailField()
                user_type =models.ForeignKey(to='UserType',to_field='id')
                u2g= models.ManyToManyField(UserGroup)

        # views.py
        
            from django.shortcuts import render,HttpResponse
            from app01 import models
            from django import forms
            from django.forms import fields as Ffields
            from django.forms import widgets as Fwidgets
            # Create your views here.

            class UserInfoModelForm(forms.ModelForm):

                is_rmb = Ffields.CharField(
                    widget=Fwidgets.CheckboxInput()
                )

                class Meta:
                    model = models.UserInfo
                    fields = '__all__'
                    # fields = ['username','email']     # 指定部分字段
                    # exclude = ['username']    # 排除部分字段
                    labels={
                        'username':'用户名',
                        'email':'邮箱',
                    }
                    help_texts={
                        'username':'...'
                    }
                    widgets = {
                        'username':Fwidgets.Textarea(attrs={'class':'c1'})
                    }
                    error_message = {
                        '__all__':{

                        },
                        'email':{
                            'required':'邮箱不能为空',
                            'invalid':'邮箱格式错误'
                        }
                    }
                    field_classes = {
                        # 'email':Ffields.URLField
                    }
                    # localized_fields=('ctime',)

                # 钩子验证同form
                def clean_username(self):
                    old = self.cleaned_data['username']
                    return old



            class UserInfoForm(forms.Form):
                username = Ffields.CharField(max_length=32)
                email =Ffields.EmailField()
                user_type =Ffields.ChoiceField(
                    choices=models.UserType.objects.values_list('id','caption')
                )
                def __init__(self,*args,**kwargs):
                    super(UserInfoForm,self).__init__(*args,**kwargs)
                    self.fields['user_type'].choices=models.UserType.objects.values_list('id','caption')



            def index(request):
                # form 代码
                # if request.method=='GET':
                #     obj =UserInfoForm()
                #     return render(request,'index.html',{'obj':obj})
                # elif request.method=="POST":
                #     obj =UserInfoForm(request.POST)
                #     obj.is_valid()
                #     obj.cleaned_data
                #     obj.errors
                #     # models.UserInfo.objects.create(**obj.cleaned_data)
                #     models.UserInfo.objects.filter(id=1).update(**obj.cleaned_data)
                #     return render(request,'index.html',{'obj':obj})

                # modelform代码
                if request.method=='GET':
                    obj = UserInfoModelForm ()
                    return render(request,'index.html',{'obj':obj})
                elif request.method=="POST":
                    obj =UserInfoModelForm(request.POST)
                    # print(obj.is_valid())
                    # print(obj.cleaned_data)
                    # print(obj.errors.as_json)
                    if obj.is_valid():
                        # obj.save()
                        # 拆分上步骤
                        instance = obj.save(False)
                        instance.save() # 只保存当前类
                        obj.save_m2m()
                    return render(request,'index.html',{'obj':obj})

            def user_list(request):
                li = models.UserInfo.objects.all().select_related('user_type')
                # li = models.UserInfo.objects.all().select_related('user_type','u2g')
                # 不能选择u2g
                return render(request,'user_list.html',{'li':li})

            def user_edit(request,nid):
                if request.method=='GET':
                    # 获取当前id用户信息,显示已存在数据
                    user_obj = models.UserInfo.objects.filter(id=nid).first()
                    mf = UserInfoModelForm(instance=user_obj)
                    return render(request,'user_edit.html',{'mf':mf,'nid':nid})
                elif request.method =='POST':
                    user_obj = models.UserInfo.objects.filter(id=nid).first()
                    mf = UserInfoModelForm(request.POST,instance=user_obj)
                    if mf.is_valid():
                        mf.save()
                    else:
                        print(mf.errors.as_json())
                    return render(request,'user_edit.html',{'mf':mf,'nid':nid})

        # index.html
        
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title></title>
            </head>
            <body>
                <form action="/index/" method="POST">
                    {% csrf_token %}
                    {{ obj.as_p}}
                    <input type="submit">
                </form>
            </body>
            </html>

        # user_list.html

            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title></title>
            </head>
            <body>
                <ul>
                    {% for row in li %}
                        <li>{{ row.username }} - {{ row.user_type.caption }} - <a href="/edit-{{ row.id }}/">编辑</a></li>
                    {% endfor %}
                </ul>
            </body>
            </html>

        # user_edit.html
        
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title></title>
            </head>
            <body>
                <form action="/edit-{{ nid }}/"method="POST">
                    {% csrf_token %}
                    {{ mf.as_p }}
                    <input type="submit">
                </form>
            </body>
            </html>


- Ajax

    - 参考博客:
        http://www.cnblogs.com/wupeiqi/articles/5703697.html
    - 原生ajax(XMLHttpRequest)    
    - jQuery
    - 伪Ajax操作(iframe)
    - 使用时机:
        如果发送的是【普通数据】
        1. jQuery
        2. XMLHttpRequest
        3. iframe
        
    
- 文件上传
    
    - Form提交
    - Ajax上传文件(xhr/jQuery)
    - 使用时机:
        如果发送的是【文件】
        1. iframe
        2. jQuery(FormData)
        3. XMLHttpRequest(FormData)

- ajax 和 文件上传 代码

    # urls.py

        url(r'^ajax/$', views.ajax),
        url(r'^ajax_json/$', views.ajax_json),

        url(r'^upload/$', views.upload),
        url(r'^upload_file/$', views.upload_file),
    
    # view.py
    
        def ajax(request):
            return render(request,'ajax.html')

        def ajax_json(request):
            print(request.POST)
            ret ={'status':True,'data':request.POST.get('username')}
            import json
            # return HttpResponse(json.dumps(ret),status=404,reason='Not Found')
            return HttpResponse(json.dumps(ret))


        def upload(request):
            return render(request,'upload.html')

        def upload_file(request):
            username = request.POST.get('username')
            fafafa = request.FILES.get('fafafa')
            print(username,fafafa)
            import os
            img_path =os.path.join('static/imgs/',fafafa.name)
            with open(img_path,'wb') as f:
                for item in fafafa.chunks():
                    f.write(item)
            ret ={'status':True,'data':img_path}
            import json
            return HttpResponse(json.dumps(ret))
            
    # ajax.html

        <body>
            <input type="text">
            <input type="button" value="Ajax1" onclick="Ajax1();">

            <!--
            ifram 演示
            <input type="text" id="url">
            <input type="button"value="发送iframe" onclick="iframeRequest();">
            <iframe id= 'ifm' src="http://www.baidu.com" frameborder="0"></iframe>
            -->

            <form action="/ajax_json/"method="POST" target="ifm1">
                <iframe id="ifm1" name="ifm1" ></iframe>
                <input type="text"name="username">
                <input type="text"name="email">
                <input type="submit" value="Form提交" onclick="submitForm();">
            </form>

            <script src="/static/jquery-1.12.4.js"></script>
            <script>
                //兼容性设置
                function getXHR(){
                    var xhr = null;
                    if (XMLHttpRequest){
                        xhr = new XMLHttpRequest();
                    }else{
                        xhr = new ActiveXObject('Microsoft.XMLHTTP');
                    }
                    return xhr;
                }
                //原生 ajax get请求
                /*
                function Ajax1(){
                    var xhr = new XMLHttpRequest();
                    xhr.open('GET','/ajax_json/',true);
                    xhr.onreadystatechange = function () {
                        if (xhr.readyState ==4){
                            console.log(xhr.responseText);
                            var obj = JSON.parse(xhr.responseText);
                            console.log(obj);
                        }
                    };
                    xhr.setRequestHeader('k1','v1');
                    xhr.send('name=root;pwd=123');
                };
                */

                //原生 ajax post请求
                function Ajax1(){
                    //未包含csrf_tonken
                    // POST发送需要加请求头
                    var xhr = getXHR();
                    //var xhr = new XMLHttpRequest();
                    xhr.open('POST','/ajax_json/',true);
                    xhr.onreadystatechange = function () {
                        if (xhr.readyState ==4){
                            console.log(xhr.responseText);
                            var obj = JSON.parse(xhr.responseText);
                            console.log(obj);
                        }
                    };
                    xhr.setRequestHeader('k1','v1');//csrf_token
                    xhr.setRequestHeader('Content_Type','application/x-www-form-urlencoded');
                    xhr.send('name=root;pwd=123');
                }


                /*
                // jquery ajax,参数a1,a2 有一个同xhr
                $.ajax({
                    success: function (arg, a1, a2) { }
                })
                */


                /*
                iframe 演示
                function iframeRequest(){
                    var url = $('#url').val();
                    $('#ifm').attr('src',url);
                }
                */

                function submitForm(){
                    $('#ifm1').load(function () {
                        var text = $('#ifm1').contents().find('body').text();
                        // console.log(text);
                        var obj =JSON.parse(text);
                    })
                }
            </script>
        </body>
        </html>    
        
    # upload.html
    
        <head>
            <meta charset="UTF-8">
            <title></title>
            <style>
                .upload{
                    display: inline-block;
                    padding: 8px;
                    background-color:cornflowerblue;
                    position: absolute;
                    top:0;
                    bottom: 0;
                    right:0;
                    left:0;
                    z-index: 90;
                }
                .file{
                    width: 100px;height: 50px;
                    opacity: 0;
                    position: absolute;
                    top:0;
                    bottom: 0;
                    right:0;
                    left:0;
                    z-index: 100;
                }
            </style>
        </head>
        <body>
            <div style="position: relative; width: 100px;height: 50px;">
                <input class="file" type="file" id="fafafa" name="afafaf">
                <a class="upload" >上传</a>
            </div>
            <input type="submit" value="提交XHR" onclick="xhrSubmit();">
            <input type="submit" value="提交jquery" onclick="jqSubmit();">

            <hr>

            <form id="form1" action="/upload_file/"method="POST" enctype="multipart/form-data" target="ifm1">
                <iframe id="ifm1" name="ifm1" style="display: none;"></iframe>
                <input type="file"name="fafafa" onchange="changeUpload();">
        {#        <input type="submit" value="Form提交" onclick="ifmSubmit();">#}
            </form>
            <div id="preview"></div>

            <script src="/static/jquery-1.12.4.js"></script>
            <script>
                function changeUpload(){
                    $('#ifm1').load(function () {
                        var text = $('#ifm1').contents().find('body').text();
                        var obj =JSON.parse(text);

                        $('#preview').empty();
                        var imgTag = document.createElement('img');
                        imgTag.src='/'+ obj.data;
                        $('#preview').append(imgTag);
                    });
                    $("#form1").submit();
                }

                function jqSubmit(){
                    var file_obj = document.getElementById('fafafa').files[0];
                    var xhr = new XMLHttpRequest();
                    var fd = new FormData();
                    fd.append('username','root');
                    fd.append('fafafa',file_obj);
                    $.ajax({
                        url:'/upload_file/',
                        type:'POST',
                        data:fd,
                        processData:false,
                        contentType:false,
                        success: function (arg, a1, a2) {
                            console.log(arg);
                            console.log(a1);
                            console.log(a2);
                        }
                    })
                }

                function xhrSubmit(){
                    var file_obj = document.getElementById('fafafa').files[0];
                    var xhr = new XMLHttpRequest();
                    var fd = new FormData();
                    fd.append('username','root');
                    fd.append('fafafa',file_obj);
                    xhr.open('POST','/upload_file/',true);
                    xhr.onreadystatechange = function () {
                        if (xhr.readyState ==4){
                            console.log(xhr.responseText);
                            var obj = JSON.parse(xhr.responseText);
                            console.log(obj);
                        }
                    };
                    xhr.send(fd);
                }

                function ifmSubmit(){
                    $('#ifm1').load(function () {
                        var text = $('#ifm1').contents().find('body').text();
        {#                console.log(text);#}
                        var obj =JSON.parse(text);

                        $('#preview').empty();
                        var imgTag = document.createElement('img');
                        imgTag.src='/'+ obj.data;
                        $('#preview').append(imgTag)
                    })
                }
            </script>
        </body>



- JSONP

    # pip3 install requests
    
    import requests
    request.get('http://www.baidu.com')
    request.post('http://www.baidu.com')
    
    # 由于浏览器具有同源策略会阻止Ajax请求
    # 但不阻止<script src='...'></script>)
    
    # 巧妙:
        - 创建script标签
        - src=远程地址
        - 返回的数据必须是js格式
        
    # 只能发GET请求
    
    # 提供接口:
    
        def jsonp(request):
            func = request.GET.get('callback')
            content = '%s(1000000)' % (func,)
            return HttpResponse(content)
            
    # jQuery请求:

        $.ajax({
                url: 'http://www.jxntv.cn/data/jmd-jxtv2.html',
                type: 'POST',
                dataType: 'jsonp',
                jsonp: 'callback',
                jsonpCallback: 'list'
            })
            
    # 参考:
        python s12 day13 JavaScript、Dom和jQuery
        https://www.cnblogs.com/wupeiqi/articles/5369773.html
            
    # CORS:
        跨站资源共享
        返回数据设置响应头
        参考资料:
            Ajax全套 cors
            https://www.cnblogs.com/wupeiqi/articles/5703697.html
    
    # 代码:
        # view.py
        
            def req(request):
                response = requests.get('http://weatherapi.market.xiaomi.com/wtr-v2/weather?cityId=101121301')
                #print(response.content) # 字节
                response.encoding = 'utf-8'
                #print(response.text)    # 字符串
                return render(request, 'req.html',{'result': response.text})
                
        # req.html    
    
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title></title>

            </head>
            <body>
                <h1>后台获取的结果</h1>
                {{ result }}
                <h1>js直接获取结果</h1>
                <input type="button" value="获取数据" onclick="getContent();" />
                <div id="container"></div>
                <script src="/static/jquery-1.8.2.js"></script>
                <script>
                    function getContent(){
                        /*
                        var xhr = new XMLHttpRequest();
                        xhr.open('GET','http://wupeiqi.com:8001/jsonp.html?k1=v1&k2=v2');
                        xhr.onreadystatechange = function(){
                            console.log(xhr.responseText);
                        };
                        xhr.send();
                        */
                        /*
                        var tag = document.createElement('script');
                        tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
                        document.head.appendChild(tag);
                        document.head.removeChild(tag);
                        */
                        $.ajax({
                            url: 'http://www.jxntv.cn/data/jmd-jxtv2.html',
                            type: 'POST',
                            dataType: 'jsonp',
                            jsonp: 'callback',
                            jsonpCallback: 'list'
                        })
                    }
                    function list(arg){
                        console.log(arg);
                    }
                </script>
            </body>
            </html>            
        
        
- Ajax2

    $.ajax({
        url: '/host/',
        type: "POST",
        data: {'k': 'v', 'list': [1,2,3,4], 'k3': JSON.stringfy({'k1': 'v'}))} --> $('form对象').serilize(),
        dataType: 'JSON',
        traditional: true,
        success: function(data){
            // data是服务器端返回的字符串
            var obj = JSON.parse(data);
            location.reload()              # 刷新
            location.href = "某个地址"     # 跳转
        }
    })
    
    $.get(url='xx',data={})
    $.getJson
    $.post

    # 建议:永远让服务器端返回一个字典
    # return HttpResponse(json.dumps(字典))        
    
        
        
- Cookie

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

    2、设置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获取(不是绝对,底层抓包可以获取到也可以被覆盖)

    3、由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

        <script src='/static/js/jquery.cookie.js'></script>
        $.cookie("list_pager_num", 30,{ path: '/' });
        
        response = HttpResponse(a)
        response.set_cookie()
        return response
        # cokies 通过响应头返回
        
        
        response = HttpResponse(a)
        response['name'] = ’alex‘
        # 自己写响应头
        
    -  示例:
    
        user_info ={
            'dachengzi':{'pwd':'123123'},
            'kangbazi':{'pwd':'456789'}
        }

        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:
                    res = redirect('/index/')
                    res.set_cookie('username',u)
                    return res
                else:
                    return render(request,'login.html')

        def index(request):
            v = request.COOKIES.get('username')
            if not v:
                return redirect('/login/')
            return render(request,'index.html',{'current_user':v})

        def cookie(request):

            request.COOKIES
            request.COOKIES['username']
            request.COOKIES.get('username')

            response =render(request,'index.html')
            response =redirect('/index/')

            # 设置cockie,关闭浏览器失效
            response.set_cookie('key','value')

            # 设置cockie,n秒后失效
            response.set_cookie('username','value',max_age=10)

            # 设置cockie,截止时间失效
            import datetime
            current_date = datetime.datetime.utcnow()
            current_date = current_date + datetime.timedelta(seconds=10)
            response.set_cookie('username','value',expires=current_date)

            # 应用:每页显示多少数量
            response.set_cookie('username','value',path='/')
            return  response    
            
    - 用户认证装饰器
    
        FBV:
            def auth(func):
                def inner(reqeust,*args,**kwargs):
                    v = reqeust.COOKIES.get('username111')
                    if not v:
                        return redirect('/login/')
                    return func(reqeust, *args,**kwargs)
                return inner
                
            @auth
            def index(reqeust):
                # 获取当前已经登录的用户
                v = reqeust.COOKIES.get('username111')
                return render(reqeust,'index.html',{'current_user': v})
    
        CBV:
                
            def auth(func):
                def inner(reqeust,*args,**kwargs):
                    v = reqeust.COOKIES.get('username111')
                    if not v:
                        return redirect('/login/')
                    return func(reqeust, *args,**kwargs)
                return inner

            from django import views
            from django.utils.decorators import method_decorator



            # 仅对get

            class Order(views.View):
                @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})                        
                                    
                                    
            # 通过dispatch 对全部

            class Order(views.View):

                @method_decorator(auth)
                def dispatch(self, request, *args, **kwargs):
                    return super(Order,self).dispatch(request, *args, **kwargs)

                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})                        

            # 对全部方法        
            @method_decorator(auth,name='dispatch')
            class Order(views.View):

                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})            

-  Session

    基于Cookie做用户验证时:敏感信息不适合放在cookie中
    
    a. Session原理
        Cookie是保存在用户浏览器端的键值对
        Session是保存在服务器端的键值对
    
    b. Cookie和Session对比
    
    c. Session配置(缺少cache)
    
    d. 示例:实现两周自动登陆
            - request.session.set_expiry(60*10)
            - SESSION_SAVE_EVERY_REQUEST = True

    PS: cookie中不设置超时时间,则表示关闭浏览器自动清除
    
    
    - session依赖于cookie
    
    - 服务器session
        request.session.get()
        request.session[x] = x
        
        request.session.clear()
        
    - 配置文件中设置默认操作(通用配置):
    
        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过期(默认)
        # set_cookie('k',123)
        SESSION_SAVE_EVERY_REQUEST = False           # 是否每次请求都保存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            
            
- session用户登陆及CSRF相关示例

    # urls.py

        url(r'^login/$', views.login),
        url(r'^index/', views.index),
        url(r'^logout/', views.logout),
    
    # views.py
    
        from django.shortcuts import render,redirect,HttpResponse

        # Create your views here.
        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
                    # 随机字符串中 设置相关内容
                    # makemigrations, migrate
                    request.session['username'] = user
                    request.session['is_login'] = True
                    if request.POST.get('rmb')=='1':
                        request.session.set_expiry(10)
                    return redirect('/index/')
                else:
                    return render(request,'login.html')
        # from django.views.decorators.csrf import csrf_exempt,csrf_protect
        # @csrf_exempt
        # @csrf_protect
        # 局部设置
        def index(request):
            # 获取当前用户字符串,并获取对应信息
            if request.session.get('is_login',None):
                return render(request,'index.html')
            else:
                return HttpResponse('go back')
    
    # index.html
    
        def logout(request):
            request.session.clear()
            return redirect('/login/')            
            
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            <h1>welcome:{{ request.session.username }}</h1>
            <a href="/logout/">leave</a>
        </body>
        </html>

    # login.html

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
        <form action="/login/"method="POST">
            {% csrf_token %}
            <input type="text" name="user">
            <input type="text" name="pwd">
            <input type="checkbox"name="rmb"value="1">10秒免登陆
            <input type="submit">
            <input id="btn" type="button"value="A提交">

            <script src="/static/jquery-1.12.4.js"></script>
            <script src="/static/jquery.cookie.js"></script>
            <script>
                $(function () {
                    $.ajaxSetup({
                        // 全局配置,对所有ajax配置请求头,携带csrf-token
                        beforeSend:function (xhr,settings) {
                            xhr.setRequestHeader('X-CSRFtoken',$.cookie('csrftoken'));
                        }
                    });
        {#            var csrf_tonken = $.cookie('csrftoken');#}
                    // get等请求时不携带x-csrftoken,需要在此做出判断,具体见其他。
                    $('#btn').click(function () {
                        $.ajax({
                            url:'/login/',
                            type:'POST',
        {#                    headers:{'X-CSRFtoken': $.cookie('csrftoken')},#}
                            data:{'user':'root','pwd':'123'},
                            success: function (arg) {

                            }
                        })
                    });
                })
            </script>
        </form>
        </body>
        </html>
            
-  CSRF

    a. CSRF原理
    b. 无CSRF时存在隐患
        # django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。
        
        # 而对于django中设置防跨站请求伪造功能有分为全局和局部。

            全局:
              中间件 django.middleware.csrf.CsrfViewMiddleware

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

        # from django.views.decorators.csrf import csrf_exempt,csrf_protect
        
    c. Form提交(CSRF)
    d. Ajax提交(CSRF)
       CSRF请求头 X-CSRFToken

    - 应用

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

    2、Ajax

        # 对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

        view.py
            
            from django.template.context import RequestContext
            # Create your views here.
          
            def test(request):
              
                if request.method == 'POST':
                    print request.POST
                    return HttpResponse('ok')
                return  render_to_response('app01/test.html',context_instance=RequestContext(request))

        text.html
            
            <!DOCTYPE html>
            <html>
            <head lang="en">
                <meta charset="UTF-8">
                <title></title>
            </head>
            <body>
                {% csrf_token %}
              
                <input type="button" onclick="Do();"  value="Do it"/>
              
                <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
                <script src="/static/plugin/jquery/jquery.cookie.js"></script>
                <script type="text/javascript">
                    var csrftoken = $.cookie('csrftoken');
              
                    function csrfSafeMethod(method) {
                        // these HTTP methods do not require CSRF protection
                        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
                    }
                    $.ajaxSetup({
                        beforeSend: function(xhr, settings) {
                            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                                xhr.setRequestHeader("X-CSRFToken", csrftoken);
                            }
                        }
                    });
                    function Do(){
              
                        $.ajax({
                            url:"/app01/test/",
                            data:{id:1},
                            type:'POST',
                            success:function(data){
                                console.log(data);
                            }
                        });
              
                    }
                </script>
            </body>
            </html>

    3、更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

- 中间件

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

    # 在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

    # 与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类

    # 中间件中可以定义四个方法,分别是:

        process_request(self,request)
        process_view(self, request, callback, callback_args, callback_kwargs)
        process_template_response(self,request,response)
        process_exception(self, request, exception)
        process_response(self, request, response)

        # 以上方法的返回值可以是None和HttpResonse对象,
        # 如果是None,则继续按照django定义的规则向下执行,
        # 如果是HttpResonse对象,则直接将该对象返回给用户。
    
    代码待添加


缓存

    # 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,
    # 当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,
    # 缓存将一个某个views的返回值保存至内存或者memcache中,
    # 5分钟内再有人来访问时,则不再去执行view中的操作,
    # 而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

    Django中提供了6种缓存方式:

        开发调试
        内存
        文件
        数据库
        Memcache缓存(python-memcached模块)
        Memcache缓存(pylibmc模块)

    1、配置
        
        a、开发调试

            # 此为开始调试用,实际内部不做任何操作
            # 配置:
                CACHES = {
                    'default': {
                        'BACKEND': 'django.core.cache.backends.dummy.DummyCache',     
                        # 引擎
                        'TIMEOUT': 300,                                              
                        # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
                        'OPTIONS':{
                            'MAX_ENTRIES': 300,                                       
                            # 最大缓存个数(默认300)
                            'CULL_FREQUENCY': 3,                                      
                            # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
                        },
                        'KEY_PREFIX': '',                                             
                        # 缓存key的前缀(默认空)
                        'VERSION': 1,                                                 
                        # 缓存key的版本(默认1)
                        'KEY_FUNCTION' 函数名                                          
                        # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
                    }
                }


            # 自定义key
            def default_key_func(key, key_prefix, version):
                """
                Default function to generate keys.

                Constructs the key used by all other methods. By default it prepends
                the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
                function with custom key making behavior.
                """
                return '%s:%s:%s' % (key_prefix, version, key)

            def get_key_func(key_func):
                """
                Function to decide which key function to use.

                Defaults to ``default_key_func``.
                """
                if key_func is not None:
                    if callable(key_func):
                        return key_func
                    else:
                        return import_string(key_func)
                return default_key_func


        b、内存

            # 此缓存将内容保存至内存的变量中
            # 配置:
                CACHES = {
                    'default': {
                        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                        'LOCATION': 'unique-snowflake',
                    }
                }

            # 注:其他配置同开发调试版本


        c、文件

            # 此缓存将内容保存至文件
            # 配置:

                CACHES = {
                    'default': {
                        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                        'LOCATION': '/var/tmp/django_cache',
                    }
                }
            # 注:其他配置同开发调试版本


        d、数据库

            # 此缓存将内容保存至数据库

            # 配置:
                CACHES = {
                    'default': {
                        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                        'LOCATION': 'my_cache_table', # 数据库表
                    }
                }

            # 注:执行创建表命令 python manage.py createcachetable


        e、Memcache缓存(python-memcached模块)

            # 此缓存使用python-memcached模块连接memcache

                CACHES = {
                    'default': {
                        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                        'LOCATION': '127.0.0.1:11211',
                    }
                }

                CACHES = {
                    'default': {
                        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                        'LOCATION': 'unix:/tmp/memcached.sock',
                    }
                }   

                CACHES = {
                    'default': {
                        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
                        'LOCATION': [
                            '172.19.26.240:11211',
                            '172.19.26.242:11211',
                        ]
                    }
                }


        f、Memcache缓存(pylibmc模块)

            # 此缓存使用pylibmc模块连接memcache
            
            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                    'LOCATION': '127.0.0.1:11211',
                }
            }

            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                    'LOCATION': '/tmp/memcached.sock',
                }
            }   

            CACHES = {
                'default': {
                    'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
                    'LOCATION': [
                        '172.19.26.240:11211',
                        '172.19.26.242:11211',
                    ]
                }
            }


        g. Redis缓存(依赖:pip3 install django-redis)

            CACHES = {
                "default": {
                    "BACKEND": "django_redis.cache.RedisCache",
                    "LOCATION": "redis://127.0.0.1:6379",
                    "OPTIONS": {
                        "CLIENT_CLASS": "django_redis.client.DefaultClient",
                        "CONNECTION_POOL_KWARGS": {"max_connections": 100}
                        # "PASSWORD": "密码",
                    }
                }
            }


            from django_redis import get_redis_connection
            conn = get_redis_connection("default")



    2、应用

        a. 全站使用

           使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,
           则使用FetchFromCacheMiddleware获取内容并返回给用户,
           当返回给用户之前,判断缓存中是否已经存在,
           如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存

            MIDDLEWARE = [
                'django.middleware.cache.UpdateCacheMiddleware',
                # 其他中间件...
                'django.middleware.cache.FetchFromCacheMiddleware',
            ]

            CACHE_MIDDLEWARE_ALIAS = ""
            CACHE_MIDDLEWARE_SECONDS = ""
            CACHE_MIDDLEWARE_KEY_PREFIX = ""

        b. 单独视图缓存

            方式一:
                from django.views.decorators.cache import cache_page

                @cache_page(60 * 15)
                def my_view(request):
                    ...

            方式二:
                from django.views.decorators.cache import cache_page

                urlpatterns = [
                    url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
                ]

        c、局部视图使用

            a. 引入TemplateTag

                {% load cache %}

            b. 使用缓存

                {% cache 5000 缓存key %}
                    缓存内容
                {% endcache %}

- 信号

    Django中提供了“信号调度”,用于在框架执行操作时解耦。
    通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

    1、Django内置信号
        
        Model signals
            pre_init                    # django的modal执行其构造方法前,自动触发
            post_init                   # django的modal执行其构造方法后,自动触发
            pre_save                    # django的modal对象保存前,自动触发
            post_save                   # django的modal对象保存后,自动触发
            pre_delete                  # django的modal对象删除前,自动触发
            post_delete                 # django的modal对象删除后,自动触发
            m2m_changed                 # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
            class_prepared              # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
        Management signals
            pre_migrate                 # 执行migrate命令前,自动触发
            post_migrate                # 执行migrate命令后,自动触发
        Request/response signals
            request_started             # 请求到来前,自动触发
            request_finished            # 请求结束后,自动触发
            got_request_exception       # 请求异常后,自动触发
        Test signals
            setting_changed             # 使用test测试修改配置文件时,自动触发
            template_rendered           # 使用test测试渲染模板时,自动触发
        Database Wrappers
            connection_created          # 创建数据库连接时,自动触发

        对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:
        project 下创建py文件

            from django.core.signals import request_finished
            from django.core.signals import request_started
            from django.core.signals import got_request_exception

            from django.db.models.signals import class_prepared
            from django.db.models.signals import pre_init, post_init
            from django.db.models.signals import pre_save, post_save
            from django.db.models.signals import pre_delete, post_delete
            from django.db.models.signals import m2m_changed
            from django.db.models.signals import pre_migrate, post_migrate

            from django.test.signals import setting_changed
            from django.test.signals import template_rendered

            from django.db.backends.signals import connection_created


            def callback(sender, **kwargs):
                print("xxoo_callback")
                print(sender,kwargs)

            xxoo.connect(callback)
            # xxoo指上述导入的内容

        # projet 下的 project __init__ 下导入 import 上述py文件

            from django.core.signals import request_finished
            from django.dispatch import receiver

            @receiver(request_finished)
            def my_callback(sender, **kwargs):
                print("Request finished!")

    2、自定义信号

        a. 定义信号
            # project 下创建py文件
            import django.dispatch
            pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

        b. 注册信号
            # project 下创建py文件    
            def callback(sender, **kwargs):
                print("callback")
                print(sender,kwargs)
            
            pizza_done.connect(callback)

        c. 触发信号
            # views下使用
            
            from 路径 import pizza_done
            
            pizza_done.send(sender='seven',toppings=123, size=456)

            由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。

            
            
- 分页(自定义的分页)
        
    - html
        {{ page_str|safe }}
        
    - views    
        
        from django.utils.safestring import mark_safe
        mark_safe(page_str)
        
    - 分页示例    
    

- 分页示例

    # utils\pagination.py

        from django.utils.safestring import mark_safe

        class Page:
            def __init__(self, current_page, data_count, per_page_count=10, pager_num=9):
                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 = []
                flag_fir = 0
                flag_end = 1

                if self.total_count < self.pager_num:
                    flag_end = 0
                    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:
                        flag_fir = 1
                        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:
                            flag_end = 0
                            end_index = self.total_count + 1
                            start_index = self.total_count - self.pager_num + 1

                fir = '<a class="page" href="%s?p=%s">%s</a>' % (base_url,1,1)
                if flag_fir:
                    page_list.append(fir)

                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)

                end = '<a class="page" href="%s?p=%s">%s</a>' % (base_url,self.total_count,self.total_count)
                if flag_end:
                    page_list.append(end)

                jump = """
                <input style="width:50px;height:20px;" type='text'/><a onclick='jumpTo(this, "%s?p=");'> GO</a>
                <script>
                    function jumpTo(ths,base){
                        var val = ths.previousSibling.value;
                            if( /^\d+$/.test(val) && val < %s ){
                                location.href = base + val;
                            }
                    }
                </script>
                """ % (base_url,self.total_count,)

                page_list.append(jump)
                page_str = mark_safe("".join(page_list))
                return page_str
        
    
    # html(含基于cookies的跳转,插件:jquery-1.12.4.js jquery.cookie.js)

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title></title>
            <style>
                .pagination .page{
                    display: inline-block;
                    padding: 5px;
                    
                    margin: 5px;
                }
                .pagination .page.active{
                    background-color: cornflowerblue;
                    color: white;
                }
            </style>
        </head>
        <body>
            <ul>
                {% for item in li %}
                    <li>{{ item }}</li>
                {% endfor %}
            </ul>

            <div>
                <select id="ps" onchange="changePageSize(this)">
                    <option value="10">10</option>
                    <option value="30">30</option>
                    <option value="50">50</option>
                    <option value="100">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');
                        $('#ps').val(v);
                });
                function changePageSize(ths){
                    var v = $(ths).val();
                    console.log(v);
                    $.cookie('per_page_count',v, {'path': "/user_list/"});
                    location.reload();
                }
            </script>
        </body>
        </html>

    # urls.py
    
         url(r'^user_list/', views.user_list),
        
    # views.py

        from  utils import pagination
        LIST = []
        for i in range(499):
            LIST.append(i)

        def user_list(request):
            current_page = request.GET.get('p', 1)
            current_page = int(current_page)

            val = request.COOKIES.get('per_page_count',10)
            val = int(val)
            
            page_obj = pagination.Page(current_page,len(LIST),val)
            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})
            
- 组合搜索

    # model.py
        from django.db import models

        # Create your models here.
        class Category(models.Model):
            caption = models.CharField(max_length=16)

        class ArticleType(models.Model):
            caption = models.CharField(max_length=16)

        class Article(models.Model):
            title = models.CharField(max_length=32)
            content = models.CharField(max_length=255)

            category = models.ForeignKey(Category)
            article_type = models.ForeignKey(ArticleType)

            # type_choice=(
            #     (1,'Python'),
            #     (2,'Openstack'),
            #     (3,'Linux'),
            # )
            # article_type = models.IntegerField(choices=type_choice)
            # 内存级别分类
    # url.py
    
        from app01 import views
        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^article-(?P<article_type_id>\d+)-(?P<category_id>\d+).html', views.article,name='article'),
        ]
    # views.py
    
        from django.shortcuts import render
        from app01 import models
        # Create your views here.
        def article(request,*args,**kwargs):
            # print(request.path_info)
            # from django.urls import reverse
            # url = reverse('article',kwargs={'article_type_id': '1', 'category_id': '1'})
            # print(url)
            print(kwargs)
            # {'article_type_id': '1', 'category_id': '1'}
            # url 中字段设置需与数据库中参数一致,方可如此传递**kwargs
            condition ={}
            for k,v in kwargs.items():
                kwargs[k] = int(v)
                if v == '0':
                    pass
                else:
                    condition[k] = v

            article_type_list= models.ArticleType.objects.all()

            # article_type_list = models.Article.type_choice
            # 内存级别分类时

            category_list= models.Category.objects.all()
            # c = {'article_type_id': '1', 'category_id': '1'}
            result = models.Article.objects.filter(**condition)

            return render(
                request,
                'article.html',
                {
                    'result':result,
                    'article_type_list':article_type_list,
                    'category_list':category_list,
                    'arg_dict':kwargs
                })

    # article.html(含simple_tag)

        {% load filter %}
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title></title>
            <style>
                .condition a{
                   display: inline-block;
                    padding: 3px 5px;
                    border: 1px solid #DDDDDD;
                    margin: 5px;
                }
                .condition a.active{
                    background-color: deepskyblue;
            </style>

        </head>
        <body>
            <h1>过滤条件</h1>
            <div class="condition">
                <div>
                    {% filter_all arg_dict 'article_type_id' %}
                    <!--
                    {% if arg_dict.article_type_id == 0 %}
                        <a class="active" href="/article-0-{{ arg_dict.category_id }}.html" >全部</a>
                    {% else %}
                        <a href="/article-0-{{ arg_dict.category_id }}.html" >全部</a>
                    {% endif %}
                    -->

                    {% filter_article_type article_type_list arg_dict %}
                    <!--
                    {% for row in article_type_list %}
                        {% if row.id == arg_dict.article_type_id %}
                            <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a>
                        {% else %}
                            <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a>
                        {% endif %}
                    {% endfor %}
                    -->
                </div>

                <div>
                    {% filter_all arg_dict 'category_id' %}
                    <!--
                    {% if arg_dict.category_id == 0 %}
                        <a class="active" href="/article-{{ arg_dict.article_type_id }}-0.html" >全部</a>
                    {% else %}
                        <a href="/article-{{ arg_dict.article_type_id }}-0.html" >全部</a>
                    {% endif %}
                    -->

                    {% for row in category_list %}
                        {% if row.id == arg_dict.category_id %}
                            <a class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html" >{{ row.caption }}</a>
                        {% else %}
                            <a href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html" >{{ row.caption }}</a>
                        {% endif %}
                    {% endfor %}
                </div>
            </div>
            <h1>查询结果</h1>
            <ul>
                {% for row in result %}
                    <li>{{ row.id }} - {{ row.title }}</li>
                {% endfor %}
            </ul>
        </body>
        </html>    
        
    # app01/templatetags/filter.py
    
        from django import template
        from django.utils.safestring import mark_safe
        register = template.Library()

        @register.simple_tag
        def filter_all(arg_dict,k):
            """
            {% if arg_dict.article_type_id == 0 %}
                <a class="active" href="/article-0-{{ arg_dict.category_id }}.html" >全部</a>
            {% else %}
                <a href="/article-0-{{ arg_dict.category_id }}.html" >全部</a>
            {% endif %}
            :param arg_dict:
            :return:
            """
            if k == 'article_type_id' :
                n1 = arg_dict['article_type_id']
                n2 = arg_dict['category_id']
                if n1 == 0:
                    ret='<a class="active" href="/article-0-%s.html" >全部</a>' % n2
                else:
                    ret='<a  href="/article-0-%s.html" >全部</a>' % n2
            else:
                 n1 = arg_dict['category_id']
                 n2 = arg_dict['article_type_id']
                 if n1 == 0:
                     ret='<a class="active" href="/article-%s-0.html" >全部</a>' % n2
                 else:
                     ret='<a  href="article-%s-0.html" >全部</a>' % n2
            return mark_safe(ret)

        @register.simple_tag
        def filter_article_type(article_type_list,arg_dict):
            """
            {% for row in article_type_list %}
                {% if row.id == arg_dict.article_type_id %}
                    <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a>
                {% else %}
                    <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a>
                {% endif %}
            {% endfor %}
            :return:
            """
            ret =[]
            for row in article_type_list:
                if row.id == arg_dict['article_type_id']:
                    temp = '<a class="active" href="/article-%s-%s.html">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
                else:
                    temp = '<a href="/article-%s-%s.html">%s</a>' %(row.id,arg_dict['category_id'],row.caption)
                ret.append(temp)

                """
                if row[0] == arg_dict['article_type_id']:
                    temp = '<a class="active" href="/article-%s-%s.html">%s</a>' %(row[0],arg_dict['category_id'],row[1])
                else:
                    temp = '<a href="/article-%s-%s.html">%s</a>' %(row[0],arg_dict['category_id'],row[1])
                ret.append(temp)
                # 内存级别分类
                """

            return mark_safe(''.join(ret))

posted @ 2020-01-16 20:47  badweather  阅读(109)  评论(0编辑  收藏  举报