Python全棧開發之2一、django

http://www.cnblogs.com/wupeiqi/articles/5237704.htmljavascript

http://www.cnblogs.com/wupeiqi/articles/5246483.htmlhtml

http://www.cnblogs.com/yuanchenqi/articles/5786089.html前端

基本配置

經常使用命令

  django-admin startproject sitenamejava

  python manage.py runserver 0.0.0.0
  python manage.py startapp appname
  python manage.py syncdb
  python manage.py makemigrations
  python manage.py migratepython

  python manage.py createsuperusermysql

2、數據庫配置(mysql)

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'dbname',
    'USER': 'root',
    'PASSWORD': 'xxx',
    'HOST': '',
    'PORT': '',
    }
}


# 因爲Django內部鏈接MySQL時使用的是MySQLdb模塊,而python3中還無此模塊,因此須要使用pymysql來代替
# 以下設置放置的與project同名的配置的 __init__.py文件中
  
import pymysql
pymysql.install_as_MySQLdb()

3、配置模板和靜態文件

TEMPLATE_DIRS = (
        os.path.join(BASE_DIR,'templates'),
    )
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) # 特有的靜態文件夾放在app裏面, # 模板裏面使用靜態文件 <script src="/static/jquery-1.12.4.js"></script>

最後記得在setting裏面註冊appjquery

Django流程

1、MTV模式

MVC模式:所謂MVC就是把web應用分爲模型(M),控制器(C),視圖(V)三層;他們之間以一種插件似的,鬆耦合的方式鏈接在一塊兒。模型負責業務對象與數據庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調用模型和視圖完成用戶的請求。git

               

Django的MTV模式本質上與MVC模式沒有什麼差異,也是各組件之間爲了保持鬆耦合關係,只是定義上有些許不一樣,Django的MTV分別表明:web

       Model(模型):負責業務對象與數據庫的對象(ORM)ajax

       Template(模版):負責如何把頁面展現給用戶

       View(視圖):負責業務邏輯,並在適當的時候調用Model和Template

       此外,Django還有一個url分發器,它的做用是將一個個URL的頁面請求分發給不一樣的view處理,view再調用相應的Model和Template

路由系統

URL模式以及要爲該URL模式調用的視圖函數之間的映射表,每一個路由對應一個view中的函數,對於這個URL調用這段代碼,對於那個URL調用那段代碼

參數說明:

  • 一個正則表達式字符串
  • 一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串
  • 可選的要傳遞給視圖函數的默認參數(字典形式)
  • 一個可選的name參數

傳遞的參數始終是字符串

from django.conf.urls import url
  
from . import views
  

urlpatterns = [

    # 通常
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    
     # 路由分發
    url(r'^contact/', include('django_website.contact.urls')),

    # 傳給視圖的默認參數,對應的視圖函數也必須加上同名的參數
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),

    #name參數   
    url(r'^index',views.index,name='bieming'),   
]

常見寫法實例

  

urlpatterns = [
    url(r'car', views.car, {'name': 'jaon'},),
    url(r'index', views.index, name='alias_login',),
    # url(r'index55555', views.index, name='alias_login',),
]


def car(request, name):
    return HttpResponse('car'+name)

def index(request,):
    if request.method == 'POST':
        username = request.POST.get('username')
        print(username)
        if username == 'jason':
            return HttpResponse('ok')
        else:
            return HttpResponse('error')
    return render(request, 'login.html')

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="{% url 'alias_login' %}" method="post">
        <input type="text" name="username">
        <input type="submit" value="提交">
    </form>
</body>
</html>

視圖函數  

一、HttpRequest對象的屬性:

# path:       請求頁面的全路徑,不包括域名
#
# method:     請求中使用的HTTP方法的字符串表示。全大寫表示。例如
#
#                    if  req.method=="GET":
#
#                              do_something()
#
#                    elseif req.method=="POST":
#
#                              do_something_else()
#
# GET:         包含全部HTTP GET參數的類字典對象
#
# POST:       包含全部HTTP POST參數的類字典對象
#
#              服務器收到空的POST請求的狀況也是可能發生的,也就是說,表單form經過
#              HTTP POST方法提交請求,可是表單中可能沒有數據,所以不能使用
#              if req.POST來判斷是否使用了HTTP POST 方法;應該使用  if req.method=="POST"
#
#
#
# COOKIES:     包含全部cookies的標準Python字典對象;keys和values都是字符串。
#
# FILES:      包含全部上傳文件的類字典對象;FILES中的每個Key都是<input type="file" name="" />標籤中                     name屬性的值,FILES中的每個value同時也是一個標準的python字典對象,包含下面三個Keys:
#
#             filename:      上傳文件名,用字符串表示
#             content_type:   上傳文件的Content Type
#             content:       上傳文件的原始內容
#
#
# user:       是一個django.contrib.auth.models.User對象,表明當前登錄的用戶。若是訪問用戶當前
#              沒有登錄,user將被初始化爲django.contrib.auth.models.AnonymousUser的實例。你
#              能夠經過user的is_authenticated()方法來辨別用戶是否登錄:
#              if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
#              時該屬性纔可用
#
# session:    惟一可讀寫的屬性,表明當前會話的字典對象;本身有激活Django中的session支持時該屬性纔可用。

HttpRequest對象的方法:get_full_path(),   好比:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()獲得的結果就是/index33/?name=123

二、HttpResponse對象:

對於HttpRequest對象來講,是由django自動建立的,可是,HttpResponse對象就必須咱們本身建立。每一個view請求處理方法必須返回一個HttpResponse對象。

  HttpResponse類在django.http.HttpResponse

  在HttpResponse對象上擴展的經常使用方法:頁面渲染:render,render_to_response,

                                                        頁面跳轉:redirect

                                                        locals:   能夠直接將函數中全部的變量傳給模板    

         

         

django的ORM

這裏先建立幾張表,分別是一對多和多對多,其中一對一就是一對多的時候外鍵惟一

from django.db import models

# Create your models here.


class UserType(models.Model):
    nid = models.AutoField(primary_key=True)
    caption = models.CharField(max_length=32)


class UserInfo(models.Model):
    user = models.CharField(max_length=16)
    pwd = models.CharField(max_length=16)
    email = models.EmailField()
    userType = models.ForeignKey(UserType)


class Group(models.Model):
    name = models.CharField(max_length=16)
    h2g = models.ManyToManyField('Host')


class Host(models.Model):
    hostname = models.CharField(max_length=16)
    ip = models.CharField(max_length=16)

下面來看一下表的增刪改查的簡單操做

#  第一種方式建立
    # usertype = models.UserType(caption='管理員')
    # usertype.save()

    # 第二種方式建立
    # models.UserType.objects.create(caption='普通用戶')

    # 第三種
    # userTypeDict = {'caption': '協管員'}
    # models.UserType.objects.create(**userTypeDict)

    # 帶外鍵添加數據庫 推薦使用
    # userInfoDict = {
    #     'user': 'jason',
    #     'email': 'jason123@qq.com',
    #     'pwd': '123',
    #     'userType_id': 2,
    # }

    # userInfoDict = {
    #     'user': 'jason2',
    #     'email': 'jason26663@qq.com',
    #     'pwd': '123',
    #     'userType': models.UserType.objects.filter(nid=2).first(),
    # }

    # models.UserInfo.objects.create(**userInfoDict)

    # 刪除
    # models.UserType.objects.filter(nid=3).delete()

    # 修改
    # models.UserType.objects.filter(nid=1).update(caption='超級管理員')



    # 查詢 查詢結果是QuerySet
    # ret = models.UserType.objects.all()    # select會獲取全部的映射
    # print(type(ret), ret, ret.query)       # ret 裏面保存的是對象

    # ret = models.UserType.objects.all().values('nid')  # 獲取指定映射
    # print(type(ret), ret, ret.query)        # ret 裏面保存的是字典

    # ret = models.UserType.objects.all().values_list('nid')  # 獲取指定映射
    # print(type(ret), ret, ret.query)  # ret 裏面保存的是元祖

再來看一下一對多連表查找操做

# 連表 雙下劃線使用,注意什麼狀況下使用 表名_set 什麼狀況下使用 表名__字段
    # (表名_set 獲取QuerySet對象) (表名__字段,查找過濾映射的時候用)

    # 正向查找,再多的一方查找一的一方
    # ret = models.UserInfo.objects.all().values('user', 'userType__caption')
    # print(ret)

    # ret = models.UserInfo.objects.filter(userType__caption="普通用戶").values('user', 'userType__caption')
    # print(ret)

    # 反向查找 在一的一方查找多的一方
    # 在獲取了一對多中一那一方的對象以後,要獲取多的那一方對象使用反向表名_set
    # ret = models.UserType.objects.filter(caption='普通用戶').first()
    # print(ret.nid, ret.userinfo_set, ret.userinfo_set.all(), ret.userinfo_set.all()[0].user)

    # 直接在一對多一那一方使用查找或者過濾映射的時候使用反向表名__字段
    # ret = models.UserType.objects.all().values('caption', 'userinfo__user')
    # print(ret)

最後看一下多對多連表查找操做

'''
        建立表:
        直接使用m2m
        自已定義第三張表
        自已定義第三張表 + m2m(through) 能夠經過through參數來指明存在的表

        直接使用m2m
            --- 獲取值
            add添加
            remove刪除(關係表),filter.delete()(關係表+..)
            set設置(添加、刪除)
            get_or_create
            update_or_create

        自已定義第三張表 + m2m + through
            --關係表只能獲取值 filter,all...
            經過第三張表進行操做


    '''
    '''
        # 直接使用
        class Host(models.Model):
            hid = models.AutoField(primary_key=True)
            hostname = models.CharField(max_length=32)
            ip =  models.CharField(max_length=32)
            # h2g = models.ManyToManyField('Group')
        class Group(models.Model):
            gid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=16)
        
            h2g = models.ManyToManyField('Host')
    
    
    
        # 自定義第三張表
        # class Host(models.Model):
        #     hid = models.AutoField(primary_key=True)
        #     hostname = models.CharField(max_length=32)
        #     ip =  models.CharField(max_length=32)
        #     # h2g = models.ManyToManyField('Group', through='HostToGroup')
        # class Group(models.Model):
        #     gid = models.AutoField(primary_key=True)
        #     name = models.CharField(max_length=16)
        #
        #     h2g = models.ManyToManyField('Host')
        #
        # class HostToGroup(models.Model):
        #     hgid = models.AutoField(primary_key=True)
        #     host_id = models.ForeignKey('Host')
        #     group_id = models.ForeignKey('Group')
        #     status = models.IntegerField()
        #     class Meta:
        #         # index_together = ("host_id",'goup_id') 組合索引
        #         unique_together = [
        #             ('host_id', 'group_id'),             組合惟一索引
        #         ]

    '''
# 將多臺機器分給一組 正向
    # obj = models.Group.objects.get(id=1)

    # hosts = models.Host.objects.filter(id__gt=2)
    # obj.h2g.add(*hosts)

    # host = models.Host.objects.get(id=2)
    # obj.h2g.add(host)

    # 給多個組分一臺機器 反向
    # h = models.Host.objects.get(id=1)
    # h.group_set.add(*models.Group.objects.filter(id__gt=2))
    # h.group_set.add(2)   # 能夠直接添加id或對象
    
    

    # h.group_set.remove(*models.Group.objects.filter(id__gt=3))  # 只刪除關係表
    # h.group_set.filter(id__gt=2).delete()  # group_id>2 的關係表刪除了,相應的group表數據也被刪除了

    # h.group_set.set(models.Group.objects.filter(id__gt=1), clear=True) #大於1的所有清除在添加

    # h.group_set.set(models.Group.objects.filter(id__gt=2))  # 大於2 之前存在的不清除,不存在的添加

    # h.group_set.set(models.Group.objects.filter(id__gt=4))  # 小於5的被清除

    # r = h.group_set.update_or_create(name='人事部')  # 兩張表都不存在,先在group表建立在添加到關係表中去
    # print(r)

    # r = h.group_set.update_or_create(name='pm')         # 和上面的效果同樣,爲何

    # h.group_set.get_or_create(name='te')    # 和上面的效果同樣

具體操做

補充:

  一次插入多條數據

 author_list = []
    for i in range(7):
        name = 'alex' + str(i)
        age = i
        author = models.Author(name=name, age=age)
        author_list.append(author)
    models.Author.objects.bulk_create(author_list)
一、models.AutoField  自增列 = int(11)
  若是沒有的話,默認會生成一個名稱爲 id 的列,若是要顯示的自定義一個自增列,必須將給列設置爲主鍵 primary_key=True。
二、models.CharField  字符串字段
  必須 max_length 參數
三、models.BooleanField  布爾類型=tinyint(1)
  不能爲空,Blank=True
四、models.ComaSeparatedIntegerField  用逗號分割的數字=varchar
  繼承CharField,因此必須 max_lenght 參數
五、models.DateField  日期類型 date
  對於參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次建立添加,以後的更新再也不改變。
六、models.DateTimeField  日期類型 datetime
  同DateField的參數
七、models.Decimal  十進制小數類型 = decimal
  必須指定整數位max_digits和小數位decimal_places
八、models.EmailField  字符串類型(正則表達式郵箱) =varchar
  對字符串進行正則表達式
九、models.FloatField  浮點類型 = double
十、models.IntegerField  整形
十一、models.BigIntegerField  長整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
十二、models.IPAddressField  字符串類型(ip4正則表達式)
1三、models.GenericIPAddressField  字符串類型(ip4和ip6是可選的)
  參數protocol能夠是:both、ipv四、ipv6
  驗證時,會根據設置報錯
1四、models.NullBooleanField  容許爲空的布爾類型
1五、models.PositiveIntegerFiel  正Integer
1六、models.PositiveSmallIntegerField  正smallInteger
1七、models.SlugField  減號、下劃線、字母、數字
1八、models.SmallIntegerField  數字
  數據庫中的字段有:tinyint、smallint、int、bigint
1九、models.TextField  字符串=longtext
20、models.TimeField  時間 HH:MM[:ss[.uuuuuu]]
2一、models.URLField  字符串,地址正則表達式
2二、models.BinaryField  二進制
2三、models.ImageField   圖片
2四、models.FilePathField 文件

更多字段
一、null=True
  數據庫中字段是否能夠爲空
二、blank=True
  django的 Admin 中添加數據時是否可容許空值
三、primary_key = False
  主鍵,對AutoField設置主鍵後,就會代替原來的自增 id 列
四、auto_now 和 auto_now_add
  auto_now   自動建立---不管添加或修改,都是當前操做的時間
  auto_now_add  自動建立---永遠是建立時的時間
五、choices
GENDER_CHOICE = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
六、max_length
七、default  默認值
八、verbose_name  Admin中字段的顯示名稱
九、name|db_column  數據庫中的字段名稱
十、unique=True  不容許重複
十一、db_index = True  數據庫索引
十二、editable=True  在Admin裏是否可編輯
1三、error_messages=None  錯誤提示
1四、auto_created=False  自動建立
1五、help_text  在Admin中提示幫助信息
1六、validators=[]
1七、upload-to

更多參數
# 獲取個數
    #
    # models.Tb1.objects.filter(name='seven').count()

    # 大於,小於
    #
    # models.Tb1.objects.filter(id__gt=1)              # 獲取id大於1的值
    # models.Tb1.objects.filter(id__lt=10)             # 獲取id小於10的值
    # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id大於1 且 小於10的值

    # in
    #
    # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於十一、2二、33的數據
    # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

    # contains
    #
    # models.Tb1.objects.filter(name__contains="ven")
    # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
    # models.Tb1.objects.exclude(name__icontains="ven")

    # range
    #
    # models.Tb1.objects.filter(id__range=[1, 2])   # 範圍bettwen and

    # 其餘相似
    #
    # startswith,istartswith, endswith, iendswith,

    # order by
    #
    # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
    # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc

    # limit 、offset
    #
    # models.Tb1.objects.all()[10:20]

    # group by
    from django.db.models import Count, Min, Max, Sum
    # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
    # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

雙下畫線操做

 

示例、用Q進行簡單搜索 

# F 使用查詢條件的值
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)

    # Q 構建搜索條件
    from django.db.models import Q
    # con = Q()
    #
    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 10))
    # q1.children.append(('id', 9))
    #
    # q2 = Q()
    # q2.connector = 'OR'
    # q2.children.append(('c1', 1))
    # q2.children.append(('c1', 10))
    # q2.children.append(('c1', 9))
    #
    # con.add(q1, 'AND')
    # con.add(q2, 'AND')
    #
    # models.Tb1.objects.filter(con)

    #
    # from django.db import connection
    # cursor = connection.cursor()
    # cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
    # row = cursor.fetchone()

F和Q
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .left{
            float: left;
        }
        .clearfix:after{
            content: '.';
            clear: both;
            display: block;
            visibility: hidden;
            height: 0;
        }
    </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>
                    <option value="pages">頁數</option>
                </select>
            </div>
            <div class="left"><input type="text" name="name" /></div>
        </div>
    </div>
    <div>
        <input type="button" onclick="Search();" value="搜索" />
    </div>

    <div class="container">

    </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('-');
            new_tag.find('.icon').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 = {};

            // 獲取全部input的內容,提交數據
            $('.condition input').each(function () {
                // console.log($(this)[0])
                var n = $(this).attr('name');
                var v = $(this).val();
                var v_list = v.split(',');
                post_data_dict[n] = v_list;
            });
            console.log(post_data_dict);
            var post_data_str = JSON.stringify(post_data_dict);
            $.ajax({
                url: '/index/',
                type: 'POST',
                data: { 'post_data': post_data_str},
                dataType: 'json',
                success: function (arg) {
                    // 字符串 "<table>" +
                    if(arg.status){
                        var table = document.createElement('table');
                        table.setAttribute('border',1);
                        // [{,name,pubdate,price,caption},]
                        $.each(arg.data, function(k,v){
                            var tr = document.createElement('tr');

                            var td1 = document.createElement('td');
                            td1.innerText = v['name'];
                            var td2 = document.createElement('td');
                            td2.innerText = v['price'];
                            var td3 = document.createElement('td');
                            td3.innerText = v['book_type__caption'];
                            var td4 = document.createElement('td');
                            td4.innerText = v['pubdate'];
                            tr.appendChild(td1);
                            tr.appendChild(td2);
                            tr.appendChild(td3);
                            tr.appendChild(td4);

                            table.appendChild(tr);
                        });

                        $('.container').empty();
                        $('.container').append(table);
                    }else{
                        alert(arg.message);
                    }

                }

            })
        }
    </script>
</body>
</html>

前端index
from django.db import models

# Create your models here.


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()


class BookType(models.Model):
    caption = models.CharField(max_length=32)


class Book(models.Model):
    name = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    pubdate = models.DateField()

    authors = models.ManyToManyField(Author)
    book_type = models.ForeignKey(BookType)

後端models
from django.shortcuts import render,HttpResponse
from app01 import models
# Create your views here.
import json
def test(request):
    # models.BookType.objects.create(caption='技術')
    # models.BookType.objects.create(caption='文學')
    # models.BookType.objects.create(caption='動漫')
    # models.BookType.objects.create(caption='男人裝')

    # models.Book.objects.create(name='文藝復興',pages='100',price='40',pubdate='1992-11-2',book_type_id='1')
    # models.Book.objects.create(name='解密',pages='80',price='10', pubdate='2016-6-10',book_type_id='2')
    # models.Book.objects.create(name='刀鋒',pages='50',price='3', pubdate='2014-02-16',book_type_id='2')
    # models.Book.objects.create(name='查令十字路84號',pages='260',price='40',pubdate='1999-10-12',book_type_id='3')
    # models.Book.objects.create(name='紅樓',pages='1000',price='500', pubdate='1760-1-1',book_type_id='3')
    # models.Book.objects.create(name='將夜',pages='2000',price='300', pubdate='2010-3-3',book_type_id='1')
    # models.Book.objects.create(name='mysql從刪庫到跑路',pages='20',price='10',pubdate='1998-9-2',book_type_id='4')
    # models.Book.objects.create(name='馬克思主義',pages='50',price='100',pubdate='1937-3-3',book_type_id='2')

    return HttpResponse('ok')

import json
from datetime import date
from datetime import datetime
from decimal import Decimal
class 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)

def index(request):
    if request.method == 'POST':
        ret = {'status': False, 'message': '', 'data':None}
        try:
            post_data = request.POST.get('post_data',None)
            post_data_dict = json.loads(post_data)
            print(post_data_dict)
            # {'name': ['11', 'sdf'],'price': ['11', 'sdf']}
            # 構造搜索條件
            from django.db.models import Q
            con = Q()
            for k,v in post_data_dict.items():
                q = Q()
                q.connector = 'OR'
                for item in v:
                    q.children.append((k, item))
                con.add(q, 'AND')
            """
            ret = models.Book.objects.filter(con)
            print(ret) # queryset,[對象]

            from django.core import serializers
            data = serializers.serialize("json", ret)   # 這種方法獲取到的圖書類型是id不是book_type__caption
            print(type(data),data)
            # 字符串
            """
            """
            #ret = models.Book.objects.filter(con).values('name','book_type__caption')
            ret = models.Book.objects.filter(con).values_list('name', 'book_type__caption')
            print(ret,type(ret))
            li = list(ret)
            data = json.dumps(li)
            print(data,type(data))
            """
            result = models.Book.objects.filter(con).values('name','price','pubdate','book_type__caption')
            # ret = models.Book.objects.filter(con).values_list('name', 'book_type__caption')
            li = list(result)
            ret['status'] = True
            ret['data'] = li
        except Exception as e:
            ret['message'] = str(e)
        ret_str = json.dumps(ret, cls=JsonCustomEncoder)
        return HttpResponse(ret_str)
    return render(request, 'index.html')

後端view 

form驗證 

#!/usr/bin/env python
# coding=utf-8

from django import forms


class Forml(forms.Form):
    # username = forms.CharField()
    # pwd = forms.CharField()

    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': '郵箱格式錯誤',
    #     }
    # )
    email = forms.EmailField(
        error_messages={
            'required': '郵箱不能爲空',
            'invalid': '郵箱格式錯誤'
        }
    )

    memo = forms.CharField(
        widget=forms.Textarea()
    )

    # 自定義
    user_type_choice = (
        (0, '普通用戶'),
        (1, '高級用戶'),
    )
    # 若是從數據庫查找,則Forml裏面定義的靜態字段只會執行一次
    # 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"},
        )
    )

    # 數據庫動態的
    # 若是從數據庫查找,則Forml裏面定義的靜態字段只會執行一次,因此須要下面動態的
    # def __init__(self, *args, **kwargs):
    #     super(Forml, 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"},
    #         )
    #     )

forms
#!/usr/bin/env python
# coding=utf-8

from django.shortcuts import render

from django.http import HttpResponse

from form1.forms import Forml


def form1(req):
    f = Forml()
    if req.method == 'POST':
        f = Forml(req.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)
            # from django.forms.utils import ErrorDict
            
            print(type(f.errors), f.errors)
        return render(req, 'account/form1.html', {'error': f.errors, 'form': f})
    return render(req, 'account/form1.html', {'form': f})

Views
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        span{
            background-color: darkolivegreen;
        }
    </style>
</head>
<body>
<form action="/form1/" method="POST">
    <div>
        <!--<input type="text" name="username">-->
        {{form.user}}
        {% if error.user %}
        <span>{{error.user.0}}</span>
        {% endif %}
    </div>
      <div>
          {{form.pwd}}
          <!--<input type="text" name="password">-->
          {% if error.pwd %}
          <span>{{error.pwd.0}}</span>
          {% endif %}
    </div>

    <div>
        {{form.email}}
        {% if error.email %}
        <span>{{error.email.0}}</span>
        {% endif %}
    </div>

    <div>
        {{form.memo}}
        {% if error.memo %}
        <span>{{error.memo.0}}</span>
        {% endif %}
    </div>

     <div>
        {{form.book_type}}
        {% if error.book_type %}
        <span>{{error.book_type.0}}</span>
        {% endif %}
    </div>
    <button type="submit">提交</button>
    <!--<input type="submit"  value="提交"/>-->
    
</form>

</body>
</html>

前端index

 除此以外還支持自定義字段,具體用法看下面的使用

import re
from django import forms
from django.core.exceptions import ValidationError


def 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 PublishForm(forms.Form):   

    # 這裏手機號使用了本身自定義的驗證規則
    phone = forms.CharField(validators=[mobile_validate, ],   
                            error_messages={'required': u'手機不能爲空'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手機號碼'}))

cookie和session  

1、cookie

1 request.COOKIES['key']
2 request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
3     參數:
4         default: 默認值
5            salt: 加密鹽
6         max_age: 後臺控制過時時間


rep = HttpResponse(...) 或 rep = render(request, ...)
 
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密鹽',...)
    參數:
        key,              鍵
        value='',         值
        max_age=None,     超時時間
        expires=None,     超時時間(IE requires expires, so set it if hasn't been already.)
        path='/',         Cookie生效的路徑,/ 表示根路徑,特殊的:跟路徑的cookie能夠被任何url的頁面訪問
        domain=None,      Cookie生效的域名
        secure=False,     https傳輸
        httponly=False    只能http協議傳輸,沒法被JavaScript獲取(不是絕對,底層抓包能夠獲取到也能夠被覆蓋)

設置cookie

2、session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默認)
     
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路徑(默認)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默認)
    SESSION_COOKIE_SECURE = False                            # 是否Https傳輸cookie(默認)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http傳輸(默認)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默認)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否關閉瀏覽器使得Session過時(默認)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次請求都保存Session,默認修改以後才保存(默認)
 
 
 
b. 使用
 
    def index(request):
        # 獲取、設置、刪除Session中數據
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在則不設置
        del request.session['k1']
 
        # 全部 鍵、值、鍵值對
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
 
 
        # 用戶session的隨機字符串
        request.session.session_key
 
        # 將全部Session失效日期小於當前日期的數據刪除
        request.session.clear_expired()
 
        # 檢查 用戶session的隨機字符串 在數據庫中是否
        request.session.exists("session_key")
 
        # 刪除當前用戶的全部Session數據
        request.session.delete("session_key")
 
        ...

數據庫session
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置
 
 
    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路徑
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https傳輸cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http傳輸
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否關閉瀏覽器使得Session過時
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次請求都保存Session,默認修改以後才保存
 
 
 
b. 使用
 
    同上

緩存session



a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
 
 
    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串
    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路徑
    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                               # 是否Https傳輸cookie
    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http傳輸
    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否關閉瀏覽器使得Session過時
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次請求都保存Session,默認修改以後才保存
 
b. 使用
 
    同上

文件session

數據庫用於作持久化,緩存用於提升效率
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
 
b. 使用
 
    同上

緩存+數據庫session



a. 配置 settings.py
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
 
b. 使用
 
    同上


備註:保存在客戶端

加密session

3、session用戶驗證

def login_auth(func):
    def wrapper(req, *args, **kwargs):
        if not req.session.get('is_login', None):
            return redirect('/admin/login')
        return func(req, *args, **kwargs)
    return wrapper

跨站請求僞造  

1、簡介

django爲用戶實現防止跨站請求僞造的功能,經過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。而對於django中設置防跨站請求僞造功能有分爲全局和局部。

全局:

  中間件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,爲當前函數強制設置防跨站請求僞造功能,即使settings中沒有設置全局中間件。
  • @csrf_exempt,取消當前函數防跨站請求僞造功能,即使settings中設置了全局中間件。

2、普通表單

veiw中設置返回值:
  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
     或者
     return render(request, 'xxx.html', data)   #這裏也能夠看出render 和 render_to_respone 的區別
  
html中設置Token:
  {% csrf_token %}

3、ajax發送  

<!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>

前端html
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))

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

Views

django上傳文件

1、普通上傳文件

def upload_file(request):
    if request.method == "POST":
        obj = request.FILES.get('fafafa')
        f = open(obj.name, 'wb')
        for chunk in obj.chunks():
            f.write(chunk)
        f.close()
    return render(request, 'file.html')


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/upload_file/" enctype="multipart/form-data" method="POST">
        {% csrf_token %}
        <input type="file" name="fafafa" />

        <input type="submit" value="提交" />
    </form>
</body>
</html>

2、form上傳文件

class FileForm(forms.Form):
    ExcelFile = forms.FileField()


from django.db import models
class UploadFile(models.Model):
    userid = models.CharField(max_length = 30)
    file = models.FileField(upload_to = './upload/')
    date = models.DateTimeField(auto_now_add=True)


def UploadFile(request):
    uf = AssetForm.FileForm(request.POST,request.FILES)
    if uf.is_valid():
            upload = models.UploadFile()
            upload.userid = 1
            upload.file = uf.cleaned_data['ExcelFile']
            upload.save()
            
            print upload.file  

 django序列化

1、serializers

# 缺點外鍵字段不能很好顯示

from django.core import serializers
 
ret = models.BookType.objects.all()
 
data = serializers.serialize("json", ret)

2、json

有些數據結構不支持,這裏能夠經過自定義處理器來作擴展

import json 
from datetime import date 
from datetime import datetime


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

ret_str = json.dumps(ret, cls=JsonCustomEncoder)

django自定義分頁

和tornado同樣,只需修改一個地方

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django.utils.safestring import mark_safe


class Pagination:
    def __init__(self, current_page, all_item):
        try:
            page = int(current_page)
        except:
            page = 1
        if page < 1:
            page = 1

        all_pager, c = divmod(all_item, 5)
        if c > 0:
            all_pager += 1

        self.current_page = page
        self.all_pager = all_pager

    @property
    def start(self):
        return (self.current_page - 1) * 5

    @property
    def end(self):
        return self.current_page * 5

    def string_pager(self, base_url="/admin/manage/"):
        list_page = []
        if self.all_pager < 11:
            s = 1
            t = self.all_pager + 1
        else:  # 總頁數大於11
            if self.current_page < 6:
                s = 1
                t = 12
            else:
                if (self.current_page + 5) < self.all_pager:
                    s = self.current_page - 5
                    t = self.current_page + 5 + 1
                else:
                    s = self.all_pager - 11
                    t = self.all_pager + 1
        # 首頁
        # first = '<a href="%s1">首頁</a>' % base_url
        # list_page.append(first)
        # 上一頁
        # 當前頁 page
        if self.current_page == 1:
            prev = '<a href="javascript:void(0);">上一頁</a>'
        else:
            prev = '<a href="%s%s">上一頁</a>' % (base_url, self.current_page - 1,)
        list_page.append(prev)

        for p in range(s, t):  # 1-11
            if p == self.current_page:
                temp = '<a class="active" href="%s%s">%s</a>' % (base_url, p, p)
            else:
                temp = '<a href="%s%s">%s</a>' % (base_url, p, p)
            list_page.append(temp)
        if self.current_page == self.all_pager:
            nex = '<a href="javascript:void(0);">下一頁</a>'
        else:
            nex = '<a href="%s%s">下一頁</a>' % (base_url, self.current_page + 1,)

        list_page.append(nex)

        # 尾頁
        # last = '<a href="%s%s">尾頁</a>' % (base_url, self.all_pager,)
        # list_page.append(last)

        # 跳轉
        # jump = """<input type='text' /><a onclick="Jump('%s',this);">GO</a>""" % ('/index/', )
        # script = """<script>
        #     function Jump(baseUrl,ths){
        #         var val = ths.previousElementSibling.value;
        #         if(val.trim().length>0){
        #             location.href = baseUrl + val;
        #         }
        #     }
        #     </script>"""
        # list_page.append(jump)
        # list_page.append(script)
        str_page = "".join(list_page)
        return mark_safe(str_page)

模板

1、基礎語法

{{ item }}
{% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}
  forloop.counter
  forloop.first
  forloop.last 
{% if ordered_warranty %}  {% else %} {% endif %}
母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
   {% block title %}{% endblock %}
幫助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}

基本使用

2、自定義

from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError
  
register = template.Library()
  
@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3
  
@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)

建立任意 .py 文件,如:xx.py

在使用自定義simple_tag的html文件中導入以前建立的 xx.py 文件名

{% load xx %}

使用simple_tag 

{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

3、使用filter

@register.filter
def detail(value, arg):
    # 只能接受兩個參數
    allcount, remainder = arg.split(',')
    allcount = int(allcount)
    remainder = int(remainder)
    if value % allcount == remainder:
        return True
    return False


<div>
    {% for item in detail_list %}
        {% if forloop.counter|detail1:"4,0" %}
            <div>
                <p>{{ item.student__name }}</p>
            </div>
        {% endif %}
    {% endfor %}
</div>

  

django中間件 

django 中的中間件(middleware),在django中,中間件其實就是一個類,在請求到來和結束後,django會根據本身的規則在合適的時機執行中間件中相應的方法。在django項目的settings模塊中,有一個 MIDDLEWARE_CLASSES 變量,其中每個元素就是一箇中間件,穿過中間件的順序就是下面列表的註冊順序

MIDDLEWARE = [
    'middleware_test_1.middleware1.testMiddleware',
    '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',
]

下面看一下流程圖

 

正常流程,request->view->  url->views   ->response

若是request裏面直接返回了, 或者出現其餘問題,直接到最裏面的response,不走django裏面的視圖處理了

 

本身自定義的中間件類能夠定義下面幾種方法

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

本身定義的類在最新的django裏面須要繼承MiddlewareMixin

自定義中間件

from django.utils.deprecation import MiddlewareMixin


class testMiddleware(MiddlewareMixin):

    def process_request(self, request):
        print(11)

    def process_response(self, request, response):
        print(22)
        return response

建立中間件
MIDDLEWARE = [
    'middleware_test_1.middleware1.testMiddleware',
    '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',
]

註冊中間件

django緩存

因爲Django是動態網站,全部每次請求均會去數據進行相應的操做,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則再也不去執行view中的操做,而是直接從內存或者Redis中以前緩存的內容拿到,並返回。

Django中提供了6種緩存方式:

  • 開發調試
  • 內存
  • 文件
  • 數據庫
  • Memcache緩存(python-memcached模塊)
  • Memcache緩存(pylibmc模塊)

1、配置

 # 此爲開始調試用,實際內部不作任何操做
    # 配置:
        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' : default_key_func                             # 生成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
# 此緩存將內容保存至內存的變量中
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
            }
        }

    # 注:其餘配置同開發調試版本

內存


# 此緩存將內容保存至文件
    # 配置:

        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
                'LOCATION': 'filetopath',
            }
        }
    # 注:其餘配置同開發調試版本

文件


# 此緩存將內容保存至數據庫

    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
                'LOCATION': 'my_cache_table', # 數據庫表
            }
        }

    # 注:執行建立表命令 python manage.py createcachetable

數據庫


# 此緩存使用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',
            ]
        }
    }

Memcache緩存(python-memcached模塊)


# 此緩存使用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',
            ]
        }
    }

Memcache緩存(pylibmc模塊)

  

2、應用

使用中間件,通過一系列的認證等操做,若是內容在緩存中存在,則使用FetchFromCacheMiddleware獲取內容並返回給用戶,當返回給用戶以前,判斷緩存中是否已經存在,若是不存在則UpdateCacheMiddleware會將緩存保存至緩存,從而實現全站緩存

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

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

全站使用
方式一:
        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)),
        ]

單獨視圖緩存
a. 引入TemplateTag

        {% load cache %}

    b. 使用緩存

        {% cache 5000 緩存key %}
            緩存內容
        {% endcache %}

局部視圖使用

django信號量  

 Django中提供了「信號調度」,用於在框架執行操做時解耦。通俗來說,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者。

1、內置信號

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          # 建立數據庫鏈接時,自動觸發

2、使用內置信號

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指上述導入的內容

3、自定義信號

a. 定義信號
    import django.dispatch
    pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])


b. 註冊信號
def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
 
pizza_done.connect(callback)


c. 觸發信號
from 路徑 import pizza_done
 
pizza_done.send(sender='seven',toppings=123, size=456)
相關文章
相關標籤/搜索