Django【进阶篇 】
Model
到目前為止,當我們的程序涉及到數據庫相關操作時,我們一般都會這么搞:
- 創建數據庫,設計表結構和字段
- 使用 MySQLdb 來連接數據庫,并編寫數據訪問層代碼
- 業務邏輯層去調用數據訪問層執行數據庫操作
django為使用一種新的方式,即:關系對象映射(Object Relational Mapping,簡稱ORM)。
PHP:activerecord
Java:Hibernate?
? C#:Entity?Framework
django中遵循 Code Frist 的原則,即:根據代碼中定義的類來自動生成數據庫表。
一、創建表
1、基本結構
from django.db import modelsclass userinfo(models.Model):name = models.CharField(max_length=30)email = models.EmailField()memo = models.TextField() 1、models.AutoField 自增列 = int(11)如果沒有的話,默認會生成一個名稱為 id 的列,如果要顯示的自定義一個自增列,必須將給列設置為主鍵 primary_key=True。 2、models.CharField 字符串字段必須 max_length 參數 3、models.BooleanField 布爾類型=tinyint(1)不能為空,Blank=True 4、models.ComaSeparatedIntegerField 用逗號分割的數字=varchar繼承CharField,所以必須 max_lenght 參數 5、models.DateField 日期類型 date對于參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次創建添加,之后的更新不再改變。 6、models.DateTimeField 日期類型 datetime同DateField的參數 7、models.Decimal 十進制小數類型 = decimal必須指定整數位max_digits和小數位decimal_places 8、models.EmailField 字符串類型(正則表達式郵箱) =varchar對字符串進行正則表達式 9、models.FloatField 浮點類型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 長整形integer_field_ranges = {'SmallIntegerField': (-32768, 32767),'IntegerField': (-2147483648, 2147483647),'BigIntegerField': (-9223372036854775808, 9223372036854775807),'PositiveSmallIntegerField': (0, 32767),'PositiveIntegerField': (0, 2147483647),} 12、models.IPAddressField 字符串類型(ip4正則表達式) 13、models.GenericIPAddressField 字符串類型(ip4和ip6是可選的)參數protocol可以是:both、ipv4、ipv6驗證時,會根據設置報錯 14、models.NullBooleanField 允許為空的布爾類型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 減號、下劃線、字母、數字 18、models.SmallIntegerField 數字數據庫中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 時間 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正則表達式 22、models.BinaryField 二進制 23、models.ImageField 圖片 24、models.FilePathField 文件 更多字段 1、null=True數據庫中字段是否可以為空 2、blank=Truedjango的 Admin 中添加數據時是否可允許空值 3、primary_key = False主鍵,對AutoField設置主鍵后,就會代替原來的自增 id 列 4、auto_now 和 auto_now_addauto_now 自動創建---無論添加或修改,都是當前操作的時間auto_now_add 自動創建---永遠是創建時的時間 5、choices GENDER_CHOICE = ((u'M', u'Male'),(u'F', u'Female'),) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默認值 8、verbose_name Admin中字段的顯示名稱 9、name|db_column 數據庫中的字段名稱 10、unique=True 不允許重復 11、db_index = True 數據庫索引 12、editable=True 在Admin里是否可編輯 13、error_messages=None 錯誤提示 14、auto_created=False 自動創建 15、help_text 在Admin中提示幫助信息 16、validators=[] 17、upload-to 更多參數2、連表結構
- 一對多:models.ForeignKey(其他表)
- 多對多:models.ManyToManyField(其他表)
- 一對一:models.OneToOneField(其他表)
應用場景:
- 一對多:當一張表中創建一行數據時,有一個單選的下拉框(可以被重復選擇)
例如:創建用戶信息時候,需要選擇一個用戶類型【普通用戶】【金牌用戶】【鉑金用戶】等。 - 多對多:在某表中創建一行數據是,有一個可以多選的下拉框
例如:創建用戶信息,需要為用戶指定多個愛好 - 一對一:在某表中創建一行數據時,有一個單選的下拉框(下拉框中的內容被用過一次就消失了
例如:原有含10列數據的一張表保存相關信息,經過一段時間之后,10列無法滿足需求,需要為原來的表再添加5列數據
二、操作表
1、基本操作
# 增# # models.Tb1.objects.create(c1='xx', c2='oo') 增加一條數據,可以接受字典類型數據 **kwargs# obj = models.Tb1(c1='xx', c2='oo')# obj.save()# 查# # models.Tb1.objects.get(id=123) # 獲取單條數據,不存在則報錯(不建議)# models.Tb1.objects.all() # 獲取全部# models.Tb1.objects.filter(name='seven') # 獲取指定條件的數據# 刪# # models.Tb1.objects.filter(name='seven').delete() # 刪除指定條件的數據# 改# models.Tb1.objects.filter(name='seven').update(gender='0') # 將指定條件的數據更新,均支持 **kwargs# obj = models.Tb1.objects.get(id=1)# obj.c1 = '111'# obj.save() # 修改單條數據 基本操作2、進階操作(了不起的雙下劃線)
利用雙下劃線將字段和對應的操作連接起來
# 獲取個數# # 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等于11、22、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 byfrom 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" 進階操作3、連表操作(了不起的雙下劃線)
利用雙下劃線和 _set 將表之間的操作連接起來
class UserProfile(models.Model):user_info = models.OneToOneField('UserInfo')username = models.CharField(max_length=64)password = models.CharField(max_length=64)def __unicode__(self):return self.usernameclass UserInfo(models.Model):user_type_choice = ((0, u'普通用戶'),(1, u'高級用戶'),)user_type = models.IntegerField(choices=user_type_choice)name = models.CharField(max_length=32)email = models.CharField(max_length=32)address = models.CharField(max_length=128)def __unicode__(self):return self.nameclass UserGroup(models.Model):caption = models.CharField(max_length=64)user_info = models.ManyToManyField('UserInfo')def __unicode__(self):return self.captionclass Host(models.Model):hostname = models.CharField(max_length=64)ip = models.GenericIPAddressField()user_group = models.ForeignKey('UserGroup')def __unicode__(self):return self.hostname 表結構實例 user_info_obj = models.UserInfo.objects.filter(id=1).first() print user_info_obj.user_type print user_info_obj.get_user_type_display() print user_info_obj.userprofile.passworduser_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() print user_info_obj.keys() print user_info_obj.values() 一對一操作 類似一對一 1、搜索條件使用 __ 連接 2、獲取值時使用 . 連接 一對多 user_info_obj = models.UserInfo.objects.get(name=u'武沛齊') user_info_objs = models.UserInfo.objects.all()group_obj = models.UserGroup.objects.get(caption='CEO') group_objs = models.UserGroup.objects.all()# 添加數據 #group_obj.user_info.add(user_info_obj) #group_obj.user_info.add(*user_info_objs)# 刪除數據 #group_obj.user_info.remove(user_info_obj) #group_obj.user_info.remove(*user_info_objs)# 添加數據 #user_info_obj.usergroup_set.add(group_obj) #user_info_obj.usergroup_set.add(*group_objs)# 刪除數據 #user_info_obj.usergroup_set.remove(group_obj) #user_info_obj.usergroup_set.remove(*group_objs)# 獲取數據 #print group_obj.user_info.all() #print group_obj.user_info.all().filter(id=1)# 獲取數據 #print user_info_obj.usergroup_set.all() #print user_info_obj.usergroup_set.all().filter(caption='CEO') #print user_info_obj.usergroup_set.all().filter(caption='DBA') 多對多操作 # 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() 其他操作注意:xx_set中的【_set】是多對多中的固定搭配
擴展:
a、自定義上傳
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') View Codeb、Form上傳文件實例
class FileForm(forms.Form):ExcelFile = forms.FileField() Form from django.db import modelsclass UploadFile(models.Model):userid = models.CharField(max_length = 30)file = models.FileField(upload_to = './upload/')date = models.DateTimeField(auto_now_add=True) Model def UploadFile(request):uf = AssetForm.FileForm(request.POST,request.FILES)if uf.is_valid():upload = models.UploadFile()upload.userid = 1upload.file = uf.cleaned_data['ExcelFile']upload.save()print upload.file ViewForm
django中的Form一般有兩種功能:
- 輸入html
- 驗證用戶輸入
擴展:ModelForm
在使用Model和Form時,都需要對字段進行定義并指定類型,通過ModelForm則可以省去From中字段的定義
class AdminModelForm(forms.ModelForm):class Meta:model = models.Admin#fields = '__all__'fields = ('username', 'email')widgets = {'email' : forms.PasswordInput(attrs={'class':"alex"}),} View Code跨站請求偽造
一、簡介
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
對于傳統的form,可以通過表單的方式將token再次發送到服務端,而對于ajax的話,使用如下方式。
view.py
from django.template.context import RequestContext # Create your views here.def test(request):if request.method == 'POST':print request.POSTreturn 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" οnclick="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 protectionreturn (/^(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>更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
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獲取(不是絕對,底層抓包可以獲取到也可以被覆蓋)由于cookie保存在客戶端的電腦上,所以,JavaScript和jquery也可以操作cookie。
<script src='/static/js/jquery.cookie.js'></script> $.cookie("list_pager_num", 30,{ path: '/' });Session
Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:
- 數據庫(默認)
- 緩存
- 文件
- 緩存+數據庫
- 加密cookie
1、數據庫Session
Django默認支持Session,并且默認是將Session數據存儲在數據庫中,即:django_session 表中。a. 配置 settings.pySESSION_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'] = 123request.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")...2、緩存Session
a. 配置 settings.pySESSION_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傳輸cookieSESSION_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. 使用同上3、文件Session
a. 配置 settings.pySESSION_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傳輸cookieSESSION_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. 使用同上4、緩存+數據庫Session
數據庫用于做持久化,緩存用于提高效率a. 配置 settings.pySESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎b. 使用同上5、加密cookie Session
a. 配置 settings.pySESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎b. 使用同上更多參考:猛擊這里 和 猛擊這里
擴展: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內置分頁
Paginator二、自定義分頁
分頁功能在每個網站都是必要的,對于分頁來說,其實就是根據用戶的輸入計算出應該在數據庫表中的起始位置。
1、設定每頁顯示數據條數
2、用戶輸入頁碼(第一頁、第二頁...)
3、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置
4、在數據表中根據起始位置取值,頁面上輸出數據
需求又來了,需要在頁面上顯示分頁的頁面。如:[上一頁][1][2][3][4][5][下一頁]
1、設定每頁顯示數據條數
2、用戶輸入頁碼(第一頁、第二頁...)
3、設定顯示多少頁號
4、獲取當前數據總條數
5、根據設定顯示多少頁號和數據總條數計算出,總頁數
6、根據設定的每頁顯示條數和當前頁碼,計算出需要取數據表的起始位置
7、在數據表中根據起始位置取值,頁面上輸出數據
8、輸出分頁html,如:[上一頁][1][2][3][4][5][下一頁]
#!/usr/bin/env python # _*_coding:utf-8_*_ from django.utils.safestring import mark_safeclass PageInfo(object):def __init__(self,current,totalItem,peritems=5):self.__current=currentself.__peritems=peritemsself.__totalItem=totalItemdef From(self):return (self.__current-1)*self.__peritemsdef To(self):return self.__current*self.__peritemsdef TotalPage(self): #總頁數result=divmod(self.__totalItem,self.__peritems)if result[1]==0:return result[0]else:return result[0]+1def Custompager(baseurl,currentPage,totalpage): #基礎頁,當前頁,總頁數perPager=11#總頁數<11#0 -- totalpage#總頁數>11#當前頁大于5 currentPage-5 -- currentPage+5#currentPage+5是否超過總頁數,超過總頁數,end就是總頁數#當前頁小于5 0 -- 11begin=0end=0if totalpage <= 11:begin=0end=totalpageelse:if currentPage>5:begin=currentPage-5end=currentPage+5if end > totalpage:end=totalpageelse:begin=0end=11pager_list=[]if currentPage<=1:first="<a href=''>首頁</a>"else:first="<a href='%s%d'>首頁</a>" % (baseurl,1)pager_list.append(first)if currentPage<=1:prev="<a href=''>上一頁</a>"else:prev="<a href='%s%d'>上一頁</a>" % (baseurl,currentPage-1)pager_list.append(prev)for i in range(begin+1,end+1):if i == currentPage:temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)else:temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)pager_list.append(temp)if currentPage>=totalpage:next="<a href='#'>下一頁</a>"else:next="<a href='%s%d'>下一頁</a>" % (baseurl,currentPage+1)pager_list.append(next)if currentPage>=totalpage:last="<a href=''>末頁</a>"else:last="<a href='%s%d'>末頁</a>" % (baseurl,totalpage)pager_list.append(last)result=''.join(pager_list)return mark_safe(result) #把字符串轉成html語言 分頁實例總結,分頁時需要做三件事:
- 創建處理分頁數據的類
- 根據分頁數據獲取數據
- 輸出分頁HTML,即:[上一頁][1][2][3][4][5][下一頁]
緩存
由于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】) }}# 自定義keydef default_key_func(key, key_prefix, version):"""Default function to generate keys.Constructs the key used by all other methods. By default it prependsthe `key_prefix'. KEY_FUNCTION can be used to specify an alternatefunction 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_funcelse:return import_string(key_func)return default_key_func View Codeb、內存
# 此緩存將內容保存至內存的變量中# 配置:CACHES = {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache','LOCATION': 'unique-snowflake',}}# 注:其他配置同開發調試版本 View Codec、文件
# 此緩存將內容保存至文件# 配置: CACHES = {'default': {'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache','LOCATION': '/var/tmp/django_cache',}}# 注:其他配置同開發調試版本 View Coded、數據庫
# 此緩存將內容保存至數據庫# 配置:CACHES = {'default': {'BACKEND': 'django.core.cache.backends.db.DatabaseCache','LOCATION': 'my_cache_table', # 數據庫表 }}# 注:執行創建表命令 python manage.py createcachetable View Codee、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',]}} View Codef、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',]}} View Code2、應用
a. 全站使用
使用中間件,經過一系列的認證等操作,如果內容在緩存中存在,則使用FetchFromCacheMiddleware獲取內容并返回給用戶,當返回給用戶之前,判斷緩存中是否已經存在,如果不存在則UpdateCacheMiddleware會將緩存保存至緩存,從而實現全站緩存MIDDLEWARE = ['django.middleware.cache.UpdateCacheMiddleware',# 其他中間件...'django.middleware.cache.FetchFromCacheMiddleware',]CACHE_MIDDLEWARE_ALIAS = ""CACHE_MIDDLEWARE_SECONDS = ""CACHE_MIDDLEWARE_KEY_PREFIX = "" View Codeb.?單獨視圖緩存
方式一:from django.views.decorators.cache import cache_page@cache_page(60 * 15)def my_view(request):...方式二:from django.views.decorators.cache import cache_pageurlpatterns = [url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),] View Codec、局部視圖使用
a. 引入TemplateTag{% load cache %}b. 使用緩存{% cache 5000 緩存key %}緩存內容{% endcache %} View Code更多:猛擊這里
序列化
關于Django中的序列化主要應用在將數據庫中檢索的數據返回給客戶端用戶,特別的Ajax請求一般返回的為Json格式。
1、serializers
from django.core import serializersret = models.BookType.objects.all()data = 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 json from datetime import date from datetime import datetime class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, datetime): return o.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field, date): return o.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, field) # ds = json.dumps(d, cls=JsonCustomEncoder)信號
Django中提供了“信號調度”,用于在框架執行操作時解耦。通俗來講,就是一些動作發生的時候,信號允許特定的發送者去提醒一些接受者。
1、Django內置信號
Model signalspre_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 signalspre_migrate # 執行migrate命令前,自動觸發post_migrate # 執行migrate命令后,自動觸發Request/response signalsrequest_started # 請求到來前,自動觸發request_finished # 請求結束后,自動觸發got_request_exception # 請求異常后,自動觸發Test signalssetting_changed # 使用test測試修改配置文件時,自動觸發template_rendered # 使用test測試渲染模板時,自動觸發Database Wrappersconnection_created # 創建數據庫連接時,自動觸發對于Django內置的信號,僅需注冊指定信號,當程序執行相應操作時,自動觸發注冊函數:
from django.core.signals import request_finishedfrom django.core.signals import request_startedfrom django.core.signals import got_request_exceptionfrom django.db.models.signals import class_preparedfrom django.db.models.signals import pre_init, post_initfrom django.db.models.signals import pre_save, post_savefrom django.db.models.signals import pre_delete, post_deletefrom django.db.models.signals import m2m_changedfrom django.db.models.signals import pre_migrate, post_migratefrom django.test.signals import setting_changedfrom django.test.signals import template_renderedfrom django.db.backends.signals import connection_createddef callback(sender, **kwargs):print("xxoo_callback")print(sender,kwargs)xxoo.connect(callback)# xxoo指上述導入的內容 View Code from django.core.signals import request_finished from django.dispatch import receiver@receiver(request_finished) def my_callback(sender, **kwargs):print("Request finished!") View Code2、自定義信號
a. 定義信號
import django.dispatchpizza_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_donepizza_done.send(sender='seven',toppings=123, size=456)由于內置信號的觸發者已經集成到Django中,所以其會自動調用,而對于自定義信號則需要開發者在任意位置觸發。
更多:猛擊這里
?
轉載于:https://www.cnblogs.com/wanghzh/p/5991911.html
總結
以上是生活随笔為你收集整理的Django【进阶篇 】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一篇RxJava友好的文章(一)
- 下一篇: 第二章 spring