首页 > 代码库 > 【Python之路】第二十三篇--Django【进阶篇】

【Python之路】第二十三篇--Django【进阶篇】

文件配置

1.模版Templates文件配置:

TEMPLATE_DIRS = (        os.path.join(BASE_DIR,‘templates‘),    )

2.静态文件static配置:

STATICFILES_DIRS = (        os.path.join(BASE_DIR,‘static‘),    )
Q搜索示例

1.利用Q的特性,设计多条件搜索。

技术分享
con = Q()q1 = Q()q1.connector = ORq1.children.append((id, 1))q1.children.append((id, 10))q1.children.append((id, 9))q2 = Q()q2.connector = ORq2.children.append((c1, 1))q2.children.append((c1, 10))q2.children.append((c1, 9))con.add(q1, AND)con.add(q2, AND)ret = models.Tb1.objects.filter(con)         #QuerySetli = list(ret)         # 转换成list 
demo

技术分享

技术分享
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .left{            float: left;        }        .clearfix:after{            content: ‘x‘;            visibility: hidden;            height: 0px;            display: block;            clear: both;        }    </style></head><body>    <div class="Condition">        <div class="item clearfix">            <div class="icon left" onclick="AddCondition(this)"> + </div>            <div class="left">                <select onchange="ChangeName(this)">                    <option value="name">书名</option>                    <option value="book_type__caption">图书类型</option>                    <option value="price">价格</option>                </select>            </div>            <div class="left"><input type="text" name="name" placeholder="多条件 ,号分割"></div>        </div>    </div>    <div><input type="button" value="提交" onclick="Search()"></div>    <div class="ConditionTable"></div>    <script src="/static/jquery-1.12.4.js"></script>    <script>        function AddCondition(ths) {            var new_tag = $(ths).parent().clone();            new_tag.find(.icon).text(-).attr(onclick,RemoveCondition(this));            $(ths).parent().parent().append(new_tag);        };        function RemoveCondition(ths) {            $(ths).parent().remove();        };        function ChangeName(ths) {            var v =$(ths).val();            $(ths).parent().next().find(input).attr(name,v);        };        function Search() {            var post_data_dict = {};            $(.Condition input).each(function () {                var n = $(this).attr(name);                var v = $(this).val();                var v_list = v.split(,);                post_data_dict[n] = v_list;            });            var post_data_str = JSON.stringify(post_data_dict);            $.ajax({                url:/index/,                type:POST,                data:{post_data:post_data_str},                dataType:json,                success:function (obj) {                    if(obj.status){                        var table = document.createElement(table);                        table.setAttribute(border,1);                        $.each(obj.data,function (k,v) {                            var tr = document.createElement(tr);                            var td1 = document.createElement(td);                            var td2 = document.createElement(td);                            var td3 = document.createElement(td);                            var td4 = document.createElement(td);                            td1.innerText = v[name];                            td2.innerText = v[price];                            td3.innerText = v[pubdate];                            td4.innerText = v[book_type__caption];                            tr.appendChild(td1);                            tr.appendChild(td2);                            tr.appendChild(td3);                            tr.appendChild(td4);                            table.appendChild(tr);                        });                        $(.ConditionTable).empty();                        $(.ConditionTable).append(table);                    }else{                    }                }            });        };            </script></body></html>
前端HTML页面
技术分享
def index(request):    print(-----------------------------------)    if request.method == POST:        result = {status: False, message: ‘‘, data: None}        try:            post_data_str = request.POST.get(post_data,None)            post_data_dict = json.loads(post_data_str)            print(post_data_dict)            Con = Q()            for k,v in post_data_dict.items():                q = Q()                q.connector = OR                for item in post_data_dict[k]:                    q.children.append((k, item))                Con.add(q, AND)            # ret = models.Book.objects.filter(Con)            # print(ret)            # from django.core import serializers            # data = http://www.mamicode.com/serializers.serialize("json", ret)            # print(type(data), data)            ret = models.Book.objects.filter(Con).values(name,price,pubdate,book_type__caption)            print(ret,type(ret))            li = list(ret)            print(li)            result[status] = True            result[data] = li        except Exception as e:            result[message] = str(e)        result_str = json.dumps(result , cls=JsonCustomEncoder)        return HttpResponse(result_str)    return render(request, index.html)
后端

注意:

1.后端得到数据返回给前端ajax时,需要序列化操作,将字符串返回给前端。

2.序列化操作时,注意json默认只能转换字典,列表,元组等对象,如果为时间,小数等对象,需要自定义扩展转换成字符串。

3.表单提交中的url地址,末尾需要带上/。  如(action="/form1/")

序列化

1、serializers

from django.core import serializersret = models.BookType.objects.all() data = http://www.mamicode.com/serializers.serialize("json", ret)

2、json.dumps

import json #ret = models.BookType.objects.all().values(‘caption‘)ret = models.BookType.objects.all().values_list(‘caption‘) ret=list(ret) result = json.dumps(ret)

由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:

技术分享
import jsonfrom datetime import datefrom datetime import datetimefrom decimal import Decimalclass JsonCustomEncoder(json.JSONEncoder):    def default(self, field):        if isinstance(field, datetime):            return field.strftime(%Y-%m-%d %H:%M:%S)        elif isinstance(field, date):            return field.strftime(%Y-%m-%d)        elif isinstance(field, Decimal):            return str(field)        else:            return json.JSONEncoder.default(self, field)   # ds = json.dumps(d, cls=JsonCustomEncoder) 
View Code
Form

Django中的Form一般有两种功能、用途:

  • 生成标签,输入html

  • 验证用户输入

1. 后端创建input标签,输入html,浏览器不同,表现不同,步骤如下:

技术分享
#!/usr/bin/env python# -*-coding:utf-8 -*-from django import formsclass Form1(forms.Form):    user = forms.CharField()    pwd = forms.CharField()
后端定义Form类型
技术分享
from app01.forms import Form1def form1(request):    f = Form1()    return render(request, account/form1.html,{form:f})
后端生成Form
技术分享
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <form action="/form1/" method="POST">        <div class="input-group">            {{ form.user }}        </div>        <div class="input-group">            {{ form.pwd }}        </div>        <div>            <input type="submit"  value=http://www.mamicode.com/"提交"/>        </div>    </form></body></html>
前端输出Form

生成的标签,可以设置属性值:

user_type_choice = (        (0, u普通用户),        (1, u高级用户),    )user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={class: "form-control"}))title = forms.CharField(widget=forms.TextInput(attrs={class: "form-control",placeholder: u标题5-20个字符}))memo = forms.CharField(widget=forms.widgets.Textarea(attrs={class: "form-control no-radius", placeholder: u详细描述, rows: 3}))
技术分享
from django import formsclass PublishForm(forms.Form):    user_type_choice = (        (0, u普通用户),        (1, u高级用户),    )    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,                                                                attrs={class: "form-control"}))    title = forms.CharField(max_length=20,                            min_length=5,                            widget=forms.TextInput(attrs={class: "form-control",                                                          placeholder: u标题5-20个字符}))    memo = forms.CharField(required=False,                           max_length=256,                           widget=forms.widgets.Textarea(attrs={class: "form-control no-radius", placeholder: u详细描述, rows: 3}))    phone = forms.CharField(widget=forms.TextInput(attrs={class: "form-control",placeholder: u手机号码}))    email = forms.EmailField(required=False,                            widget=forms.TextInput(attrs={class: "form-control", placeholder: u邮箱}))
View Code

注意:

1.类里静态字段 只在第一遍执行!, 如果动态绑定了数据,生成后就不再修改了!

class Form1(forms.Form):    def __init__(self,*args, **kwargs):        super(Form1, self).__init__(*args, **kwargs)        self.fields[book_type] =  forms.CharField(            widget=forms.widgets.Select(choices=models.BookType.objects.values_list(id,caption),attrs={class: "form-control"}))
技术分享
#!/usr/bin/env python# -*- coding:utf-8 -*-from django import formsfrom app01 import modelsclass Form1(forms.Form):    user = forms.CharField(        widget=forms.TextInput(attrs={class: c1}),        error_messages={required: 用户名不能为空},)    pwd = forms.CharField(max_length=4,min_length=2)    email = forms.EmailField(error_messages={required: 邮箱不能为空, invalid: 邮箱格式错误})    memo = forms.CharField(        widget=forms.Textarea()    )    # user_type_choice = (    #     (0, ‘普通用户‘),    #     (1, ‘高级用户‘),    # )    user_type_choice = models.BookType.objects.values_list(id,caption)    book_type = forms.CharField(        widget=forms.widgets.Select(choices=user_type_choice,attrs={class: "form-control"}))    def __init__(self,*args, **kwargs):        super(Form1, self).__init__(*args, **kwargs)        self.fields[book_type] =  forms.CharField(            widget=forms.widgets.Select(choices=models.BookType.objects.values_list(id,caption),attrs={class: "form-control"}))
完整demo

2. 验证用户输入

依据自定义的Form类,进行判断用户输入是否合法

自定义静态字段:

class Form1(forms.Form):    user = forms.CharField( required=True                            max_length=20,                            min_length=5,                            error_messages={required: u标题不能为空,                                           min_length: u标题最少为5个字符,                                           max_length: u标题最多为20个字符,                                           invalid: u标题格式错误},                            ) 

自定义正则规则:

from django import formsimport refrom django.core.exceptions import ValidationErrordef mobile_validate(value):    mobile_re = re.compile(r^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$)    if not mobile_re.match(value):        raise ValidationError(手机号码格式错误)class Form1(forms.Form):    phonenum= forms.CharField( validators=[mobile_validate, ],                            )

后端验证方法: (需要传入request.POST)

from app01.forms import Form1def form1(request):    if request.method == POST:        # 获取请求内容,做验证        f = Form1(request.POST)        if f.is_valid():            print(f.cleaned_data)        else:            # print(f.errors.get(‘user‘,None))            # print(f.errors[‘pwd‘][0])            # print(type(f.errors),f.errors)return render(request, account/form1.html,{error: f.errors,form:f})    else:        f = Form1()        return render(request, account/form1.html,{form:f})
Cookie

1、获取Cookie:

# 普通Cookierequest.COOKIES[‘key‘]
# 加密Cookierequest.get_signed_cookie(key, default=RAISE_ERROR, salt=‘‘, max_age=None) 参数: default: 默认值 salt: 加密盐 (获取Cookie解密时,需要写上,否则获取得值为None ) max_age: 后台控制过期时间

2、设置Cookie:

rep = HttpResponse(...) 或 rep = render(request, ...) rep.set_cookie(key,value,...)rep.set_signed_cookie(key,value,salt=‘加密盐‘,...)    参数:        key,              键        value=http://www.mamicode.com/‘‘,         值>

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

<script src=http://www.mamicode.com/‘/static/js/jquery.cookie.js‘></script>"list_pager_num", 30,{ path: ‘/‘ });
Session

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  • 数据库(默认)

  • 缓存

  • 文件

  • 缓存+数据库

  • 加密cookie

1、数据库Session

技术分享
a. 配置 settings.py     SESSION_ENGINE = django.contrib.sessions.backends.db   # 引擎(默认)         SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
配置 settings.py
技术分享
b. 使用     def index(request):        # 获取、设置、删除Session中数据        request.session[k1]        request.session.get(k1,None)        request.session[k1] = 123        request.session.setdefault(k1,123) # 存在则不设置        del request.session[k1]         # 所有 键、值、键值对        request.session.keys()        request.session.values()        request.session.items()        request.session.iterkeys()        request.session.itervalues()        request.session.iteritems()          # 用户session的随机字符串        request.session.session_key         # 将所有Session失效日期小于当前日期的数据删除        request.session.clear_expired()         # 检查 用户session的随机字符串 在数据库中是否        request.session.exists("session_key")         # 删除当前用户的所有Session数据        request.session.delete("session_key")         request.session.set_expiry(value)            * 如果value是个整数,session会在些秒数后失效。            * 如果value是个datatime或timedelta,session就会在这个时间后失效。            * 如果value是0,用户关闭浏览器session就会失效。            * 如果value是None,session会依赖全局session失效策略。
使用示例

2、缓存Session

技术分享
a. 配置 settings.py     SESSION_ENGINE = django.contrib.sessions.backends.cache  # 引擎    SESSION_CACHE_ALIAS = default                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置      SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
配置 settings.py

3、文件Session

技术分享
a. 配置 settings.py     SESSION_ENGINE = django.contrib.sessions.backends.file    # 引擎    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T      SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名    SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
配置 settings.py

4、缓存+数据库Session

技术分享
数据库用于做持久化,缓存用于提高效率 a. 配置 settings.py     SESSION_ENGINE = django.contrib.sessions.backends.cached_db        # 引擎
配置 settings.py

5、加密cookie Session

技术分享
a. 配置 settings.py         SESSION_ENGINE = django.contrib.sessions.backends.signed_cookies   # 引擎
配置 settings.py

更多参考:猛击这里 和 猛击这里

扩展: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内置分页

二、自定义分页

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

二、应用

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

1.对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,添加请求头

2.为了方便,获取cookie,需要用到 jquery.cookie.js 文件提供的$.cookie()方法

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

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

admin

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

  • 创建后台管理员

  • 配置url

  • 注册和配置django admin后台管理页面

1、创建后台管理员

python manage.py createsuperuser

2、配置后台管理url

url(r‘^admin/‘, include(admin.site.urls))

3、注册和配置django admin 后台管理页面

a、在admin中执行如下配置

技术分享
from django.contrib import admin  from app01 import  models  admin.site.register(models.UserType)admin.site.register(models.UserInfo)admin.site.register(models.UserGroup)admin.site.register(models.Asset)admin.site.register(models.xxxxx)  # 自己创建的表
View Code

b、设置数据表名称

技术分享
class UserType(models.Model):    name = models.CharField(max_length=50)      class Meta:        verbose_name = 用户类型        verbose_name_plural = 用户类型
View Code

c、打开表之后,设定默认显示,需要在model中作如下配置

技术分享
class UserType(models.Model):    name = models.CharField(max_length=50)       #py2    def __unicode__(self):        return self.name    #py3    def __str__(self):        return self.name
View Code
技术分享
from app01 import  models  class UserInfoAdmin(admin.ModelAdmin):    list_display = (username, password, email)
View Code

d、为数据表添加搜索功能

技术分享
from django.contrib import admin  from app01 import  models  class UserInfoAdmin(admin.ModelAdmin):    list_display = (username, password, email)    search_fields = (username, email)
View Code

e、添加快速过滤

技术分享
from django.contrib import admin  from app01 import  models  class UserInfoAdmin(admin.ModelAdmin):    list_display = (username, password, email)    search_fields = (username, email)    list_filter = (username, email)
View Code

更多:http://docs.30c.org/djangobook2/chapter06/

 

【Python之路】第二十三篇--Django【进阶篇】