1、Django 簡介
Django 是一個由 Python 寫成的開放源代碼的 Web 應用框架。它最初是被開發來用於管理勞倫斯出版集團旗下的一些以新聞內容爲主的網站的,便是 CMS(內容管理系統)軟件。並於2005年7月在 BSD 許可證下發布。這套框架是以比利時的吉普賽爵士吉他手 Django Reinhardt 來命名的。因爲 Django 的是在一個快節奏的新聞編輯室環境下開發的,它的目的是使常見的 Web 開發任務,快速和容易。javascript
MTV 模式
Django 採用了 MTV 設計模式css
上述圖大概是說:html
- URL ( urls.py )請求調度,當有緩存頁面的時候直接返回內容。
- 視圖函數( view.py )執行所請求的操做,一般包括讀寫數據庫。
- 模型( models.py )定義了 Python 中的數據並與之交互。一般包含在一個關係數據庫( MySQL、PostgreSQL SQLite 等),其餘數據存儲是可能的( XML、文本文件、LDAP、等)。
- 請求執行任務後,視圖返回一個 HTTP 響應對象(一般是通過數據處理的一個模板)。可選的:視圖能夠保存一個版本的 HTTP 響應對象,返回攜帶一個時間戳,來告訴瀏覽器這個視圖的更新時間。
- 模板一般返回 HTML 頁面。Django 模板語言提供了 HTML 的語法及邏輯。
安裝
# pip 安裝 pip install Django==1.10 # 克隆下載最新版本 git clone https://github.com/django/django.git # 導入django模塊 >>> import django >>> print(django.get_version()) 1.10
2、基本配置
一、經常使用命令
# 查看django版本 $ python -m django --version # 建立項目,名爲mysite $ django-admin startproject mysite # 啓動django $ python manage.py runserver $ python manage.py runserver 8080 $ python manage.py runserver 0.0.0.0:8000 # 建立應用程序,確保和 manage.py 是同一目錄 $ python manage.py startapp polls # 運行創造模型變化遷移 $ python manage.py makemigrations # 運行應用模型變化到數據庫 $ python manage.py migrate # admin建立管理員用戶 $ python manage.py createsuperuser
注:自動從新加載 runserver,根據須要開發服務器自動從新加載Python代碼爲每一個請求。您不須要從新啓動服務器代碼更改生效。然而,像添加文件某些操做不觸發從新啓動,因此你必須從新啓動在這些狀況下的服務器。java
基本目錄結構及做用:
mysite/ # 項目的容器,名字隨便起 manage.py # 命令行實用工具,以各類方式與該Django項目進行交互 mysite/ # 實際的Python項目 __init__.py # 空文件,導入不出錯 settings.py # 這個Django項目配置 urls.py # 這個Django項目的URL聲明; 一個Django驅動網站的「目錄」 wsgi.py # 一個入口點爲WSGI兼容的Web服務器,以知足您的項目
二、配置文件
數據庫
# 因爲Django內部鏈接MySQL時使用的是MySQLdb模塊,而python3中還無此模塊,因此須要使用pymysql來代替 # 以下設置放置的與project同名的配置的 __init__.py文件中 import pymysql pymysql.install_as_MySQLdb()
# 在settings 中修改DATABASES DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'root', 'PASSWORD': 'xxx', 'HOST': '', 'PORT': '', } }
模板 python
# 也在settings裏修改,放html文件 TEMPLATE_DIRS = ( os.path.join(BASE_DIR,'templates'), )
靜態文件mysql
# 依然在settings裏修改添加,放css,js等文件 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), )
3、路由系統
一、URL 調度
一個乾淨,優雅的 URL 方案是一個高質量的 Web 應用程序的一個重要的細節。jquery
與 tornado 不一樣的是一個 url 對應一個函數,而並不是一個類。git
像是一個新華字典的目錄,對應了 views 函數來進行處理,即這個 url 要用某個指定的 views 函數處理。github
來看如下示例,如何動態構造:web
from app1 import views urlpatterns = [ url(r'^manage1/(\d*)', views.manage1), url(r'^manage2/(?P<name>\w*)/(?P<id>\d*)', views.manage2), url(r'^manage3/(?P<name>\w*)', views.manage3,{'id':333}), ] # 須要注意 # url多傳了一個參數,那views函數得多接受一個參數
# 對應接收值 def manage1(request, age): print(age) # 18 return HttpResponse('1') def manage2(request, name, id): print(name, id) # nick 18 return HttpResponse('2') def manage3(request, name, id): print(name, id) # nick 666 return HttpResponse('3')
二級路由: 那若是映射 url 太多怎麼辦,全寫一個在 urlpatterns 顯得繁瑣,so 二級路由應用而生
# 一級路由規定 app1 開頭的都去 app1.urls 中找 # 二級在詳細規定對應 views 函數 # 一級 urlpatterns = [ url(r'^app1/', include('app1.urls')), ] # 二級 urlpatterns = [ url(r'^1$', views.manage1), ]
二、Django是如何處理一個請求
當用戶請求從您的 Django 的網站頁面,這是該系統遵循以肯定哪些 Python 代碼執行的算法:
- Django 請求是 URL 配置模塊配置。一般經過值 ROOT_URLCONF 設置,但若是傳入 HttpRequest 對象具備 urlconf 屬性(由中間件設置),它的值將代替的可使用 ROOT_URLCONF 的設置。
- Django 的負載是 Python 模塊並尋找變量 urlpatterns。這是一個 django.conf.urls.url() 實例。
- Django 的貫穿每一個 URL 模式,從而,在所請求的 URL 匹配的第一個中止。
- 一旦某個正則表達式相匹配,就運行相對應的視圖函數(或基於類的視圖)。該視圖被傳遞如下參數:
- HttpRequest 對象。
- 若是匹配的正則表達式沒有返回命名組,而後從正則表達式比賽是做爲位置參數。
- 關鍵詞參數是由由正則表達式匹配的任何命名組,由指定的可選參數的任何覆蓋的 kwargs參數 django.conf.urls.url()。
- 若是沒有正則表達式匹配,或者若是一個異常在這個過程當中的任何一點時提出,Django的調用適當的錯誤處理視圖。
三、官方示例
1> 如下代碼是官方示例:
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/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
筆記注意事項:
- 要捕獲從URL中的值,用括號括起來,會當參數傳入 views 視圖。
- 沒有必要添加一個斜線,由於每一個URL都有。例如,它
^articles
不是^/articles
。 - 在
'r'
前面的每一個正則表達式字符串中是可選的,但建議。它告訴Python字符串是「原始」 -沒有什麼字符串中應該進行轉義。
舉例請求:
- 請求
/articles/2005/03/
將匹配列表中的第三項。Django的將調用該函數 。views.month_archive(request,'2005', '03')
/articles/2005/3/
不會匹配任何 URL 模式,由於在列表中的第三項中須要兩位數字的月份。/articles/2003/
將匹配的列表,而不是第二個第一圖案,由於該圖案,以便測試,第一個是在第一測試經過。隨意利用順序插入特殊狀況是這樣的。在這裏,Django的將調用該函數views.special_case_2003(request)
/articles/2003
不匹配任何這些模式,由於每一個模式要求 URL 以斜線結束。/articles/2003/03/03/
將匹配的最終格局。Django 的將調用該函數。views.article_detail(request,'2003', '03', '03')
2> 命名組
上面的例子使用了簡單的,非命名的正則表達式組(經過括號)來捕獲 URL 的位,並經過他們的位置參數的視圖。在更高級的用法,它可使用命名 正則表達式組來捕獲 URL 位,將它們做爲關鍵字參數傳遞給視圖。
在 Python 正則表達式,命名正則表達式組的語法(?P<name>pattern)
,這裏 name
是組的名稱, pattern
就是某種模式相匹配。
下面是上面的例子中的URLconf,改寫使用命名組:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
這正好完成一樣的事情,前面的例子,一個細微的差異:捕獲的值傳遞給查看功能做爲關鍵字參數,而不是位置參數。例如:
- 請求
/articles/2005/03/
會調用函數來代替,views.month_archive(request, year='2005',month='03')
views.month_archive(request, '2005', '03')
- 請求
/articles/2003/03/03/
會調用該函數,views.article_detail(request, year='2003',month='03', day='03')
在實踐中,這意味着你的 URLconf 稍微更明確,不容易參數順序錯誤 - 你能夠在你的意見'函數定義從新排序的參數。固然,這些優勢來在簡短的費用; 一些開發任務命名組的語法醜陋,太冗長。
匹配/分組算法
這裏的URL配置解析器遵循算法,相對於正則表達式命名組與非命名組:
- 若是有任何命名參數,它會使用這些,而忽略非命名參數。
- 不然,它會經過全部非命名參數做爲位置參數。
在這兩種狀況下,被賦予按任何額外的關鍵字參數傳遞額外的選項來查看功能也將被傳遞給視圖
3> What the URLconf searches against
The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name.
For example, in a request to https://www.example.com/myapp/
, the URLconf will look for myapp/
.
In a request to https://www.example.com/myapp/?page=3
, the URLconf will look for myapp/
.
該URL配置不看請求方法。換言之,全部的請求的方法,GET,POST 等將被路由到爲相同的URL,相同的功能。
4> 捕獲的參數老是字符串
每一個捕獲的參數發送到視圖做爲普通的 Python 字符串,不管什麼樣的匹配正則表達式匹配。
例如,在該URL配置行:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
...的 year
參數傳遞給 views.year_archive()
將是一個字符串,
不是一個整數,即便 [0-9]{4}
將只匹配整數字符串。
5> 指定view的默認設置
一個方便的技巧是你的觀點的論據指定默認參數。下面是一個例子的 RLconf 和見解:
# URLconf from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/$', views.page), url(r'^blog/page(?P<num>[0-9]+)/$', views.page), ] # View (in blog/views.py) def page(request, num="1"): # Output the appropriate page of blog entries, according to num. ...
在上述的例子中,兩個 URL 模式指向同一個視圖 views.page
但第一圖案不捕獲從 URL 任何東西。若是第一個模式匹配,該 page()
函數將使用它的默認參數 num
,"1"
。若是第二圖案相匹配時, page()
將使用任何 num
值由正則表達式捕獲。
6> 包括其餘的URLconf
在任什麼時候候,你urlpatterns
能夠「include」其餘的URLconf模塊。這實質上是「roots」的一套低於其餘的網址。
例如,這裏的URL配置爲節選的Django網站 自己。它包括許多其餘的URLconf的:
from django.conf.urls import include, url urlpatterns = [ # ... snip ... url(r'^community/', include('django_website.aggregator.urls')), url(r'^contact/', include('django_website.contact.urls')), # ... snip ... ]
請注意,在這個例子中,正則表達式沒有一個$
(結束字符串匹配字符),但包括尾隨斜線。每當 Django 的遇到 include()
(django.conf.urls.include()
),它扒關閉任何匹配到該點的URL的一部分,並將剩餘的字符串所包含的URL配置用於進一步的處理。
另外一種可能性是經過使用的列表,以包括另外的網址格式 url()
實例。例如,考慮這個 URL 配置:
from django.conf.urls import include, url from apps.main import views as main_views from credit import views as credit_views extra_patterns = [ url(r'^reports/$', credit_views.report), url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report), url(r'^charge/$', credit_views.charge), ] urlpatterns = [ url(r'^$', main_views.homepage), url(r'^help/', include('apps.help.urls')), url(r'^credit/', include(extra_patterns)), ]
在這個例子中,/credit/reports/
URL將被處理 credit_views.report()
的Django圖。
從其中單個圖案前綴被重複使用的URLconf去除冗餘。
咱們能夠經過聲明的共同路徑前綴只有一次,分組,例如這個URL配置:
from django.conf.urls import include, url from . import views urlpatterns = [ url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([ url(r'^history/$', views.history), url(r'^edit/$', views.edit), url(r'^discuss/$', views.discuss), url(r'^permissions/$', views.permissions), ])), ]
7> 傳遞額外的選項來查看功能
URLconf 有一個掛鉤,能夠傳遞額外的參數給您的視圖功能,做爲一個 Python 字典。
該django.conf.urls.url()
功能能夠採起這應該是額外的參數的字典傳遞給視圖功能可選的第三個參數。
例如:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
在這個例子中,用於向請求/blog/2005/
,Django會調用 。views.year_archive(request, year='2005',foo='bar')
# 處理衝突 這可能有它能夠捕獲一個名爲關鍵字參數的URL模式,而且還傳遞參數,在其額外的參數字典相同的名稱。發生這種狀況時,在字典中的參數將被用來代替在URL捕獲的參數。
傳遞額外的選項來 include()
一樣,您能夠經過額外的選項include()
。當你經過額外的選項include()
,每一個中所包含的URL配置線將經過額外的選項。
例如,這兩個URL配置集在功能上是相同的:
# 設置一個: # main.py from django.conf.urls import include, url urlpatterns = [ url(r'^blog/', include('inner'), {'blogid': 3}), ] # inner.py from django.conf.urls import url from mysite import views urlpatterns = [ url(r'^archive/$', views.archive), url(r'^about/$', views.about), ] # 設置兩個 # main.py from django.conf.urls import include, url from mysite import views urlpatterns = [ url(r'^blog/', include('inner')), ] # inner.py from django.conf.urls import url urlpatterns = [ url(r'^archive/$', views.archive, {'blogid': 3}), url(r'^about/$', views.about, {'blogid': 3}), ]
4、視圖層
對邏輯負責處理用戶的請求並返回響應。反回能夠是HTML內容的網頁,或重定向,或404錯誤,或一個XML文件,或一個形象......此代碼能夠住在任何你想去的地方,只要它在你的Python路徑。
在一個文件中稱將視圖views.py
,放在你的項目或應用程序目錄。
一、返回快捷功能
render()
-
render(
request,
template_name,
context=None,
content_type=None,
status=None,
using=None)
[source]
- 結合給定的模板與一個給定的上下文,返回一個字典HttpResponse在渲染文本對象
所需的參數
template_name 一個模板的使用或模板序列名稱全稱。若是序列是給定的,存在於第一個模板將被使用。
可選參數
context 一組字典的值添加到模板中。默認狀況下,這是一個空的字典。
content_type MIME類型用於生成文檔。
status 爲響應狀態代碼。默認值爲200
using 這個名字一個模板引擎的使用將模板。
例子
from django.shortcuts import render def my_view(request): # View code here... return render(request, 'myapp/index.html', { 'foo': 'bar', }, content_type='application/xhtml+xml')
等價於
from django.http import HttpResponse from django.template import loader def my_view(request): # View code here... t = loader.get_template('myapp/index.html') c = {'foo': 'bar'} return HttpResponse(t.render(c, request), content_type='application/xhtml+xml')
render_to_response()
render_to_response(template_name, context=None, content_type=None, status=None, using=None)[source]
這個和 render() 差很少,不推薦,在將來可能廢棄掉
redirect()
redirect(to, permanent=False, *args, **kwargs)[source]
默認狀況下,爲臨時重定向;經過 permanent=True
設置永久重定向
def my_view(request): ... return redirect('/some/url/') def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)
二、求和響應對象
Django 使用請求和響應對象在系統間傳遞狀態。
當請求一個頁面時,Django 建立一個 HttpRequest
對象包含原數據的請求。而後 Django 加載適當的視圖,經過 HttpRequest
做爲視圖函數的第一個參數。每一個視圖負責返回一個HttpResponse
目標。
HttpRequest對象
HttpRequest.scheme一個字符串表示請求的方案(HTTP或HTTPS)一般HttpRequest.path
一個字符串的完整路徑的請求HttpRequest.method
請求的HTTP方法。這是保證要大寫 if request.method == 'GET': do_something() elif request.method == 'POST': do_something_else()HttpRequest.GET
字典像包含全部給定的HTTP GET參數對象。HttpRequest.POST
字典像包含全部給定的HTTP POST參數對象,提供請求包含表單數據。HttpRequest.COOKIES
一個標準的Python字典,包含了全部的COOKIES,key和values都是字符串HttpRequest.FILES
字典像對象包含全部上傳的文件。 html 標籤 <input type="file" name="" /> filename # 上傳的文件名 content_type # 上傳文件的類型 content # 上傳文件的內容HttpRequest.META
一個標準的Python字典包含全部可用的HTTP頭。可用標題取決於客戶端和服務器,但這裏是一些例子: CONTENT_LENGTH – 請求體的長度(一個字符串)。 CONTENT_TYPE – 請求體的類型。 HTTP_ACCEPT - 爲響應–能夠接受的內容類型。 HTTP_ACCEPT_ENCODING – 接受編碼的響應 HTTP_ACCEPT_LANGUAGE – 接受語言的反應 HTTP_HOST – 客戶端發送的HTTP主機頭。 HTTP_REFERER – 參考頁面 HTTP_USER_AGENT – 客戶端的用戶代理字符串。 QUERY_STRING – 查詢字符串,做爲一個單一的(分析的)字符串。 REMOTE_ADDR – 客戶端的IP地址 REMOTE_HOST – 客戶端的主機名 REMOTE_USER – 用戶經過Web服務器的身份驗證。 REQUEST_METHOD – 字符串,如"GET"或"POST" SERVER_NAME – 服務器的主機名 SERVER_PORT – 服務器的端口(一個字符串)。
HttpResponse對象
對於HttpRequest 對象來講,是由django自動建立的,可是,HttpResponse 對象就必須咱們本身建立。每一個 view 請求處理方法必須返回一個 HttpResponse 對象。
HttpResponse 類在 django.http.HttpResponse
字符串使用:
典型的用法是經過頁面的內容,爲一個字符串
>>> from django.http import HttpResponse >>> response = HttpResponse("Here's the text of the Web page.") >>> response = HttpResponse("Text only, please.", content_type="text/plain") # 若是你想添加內容的增量 >>> response = HttpResponse() >>> response.write("<p>Here's the text of the Web page.</p>") >>> response.write("<p>Here's another paragraph.</p>")
特性與方法:
HttpResponse.content一個bytestring表明內容HttpResponse.charset
一個字符串的字符集表示的響應將編碼HttpResponse.status_code
HTTP狀態代碼爲響應碼HttpResponse.streaming
這個屬性永遠爲假,通常用於中間件HttpResponse.closed
關閉
方法:
HttpResponse.__init__(content='', content_type=None, status=200, reason=None, charset=None)[source]
實例化類自動執行的方法HttpResponse.__setitem__(header, value)
爲給定值給定的標題名稱。都是字符串HttpResponse.__delitem__(header)
刪除標題的名稱。不區分大小寫。HttpResponse.__getitem__(header)
獲取給定標題名稱。不區分大小寫。HttpResponse.has_header(header)
檢查是否具備給定名稱的一個標題HttpResponse.setdefault(header, value)
設置一個標題,除非它已經設置。HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
設置一個cookie。參數跟標準庫的Cookie對象差很少HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True)
加密cookice,能夠用 HttpRequest.get_signed_cookie() 獲取,固然你也能夠加鹽HttpResponse.delete_cookie(key, path='/', domain=None)
刪除Cookie與給定鍵。
HttpResponse子類:
class HttpResponseRedirect[source]
構造函數的第一個參數是必需的–路徑redirectto。這是一個徹底合格的URL(例如「https://www.yahoo.com /搜索/),沒有一個絕對的路徑(例如域搜索/ /),甚至是相對路徑(如「/」)。在最後的狀況下,客戶端瀏覽器將重建完整的URL自己的電流路徑。看到HttpResponse其餘optionalconstructor參數。請注意,這將返回一個HTTP狀態代碼302。class HttpResponsePermanentRedirect[source]
像httpresponseredirect,但它返回一個永久重定向(HTTP狀態代碼301)而不是「發現」的重定向(狀態代碼302)class HttpResponseNotModified[source]
構造函數不帶任何參數和NO含量應該被添加到這一反應。使用指定一個頁面沒有被modifiedsince用戶的最後一個請求(狀態代碼304)。class HttpResponseBadRequest[source]
就像HttpResponse但使用400狀態碼class HttpResponseNotFound[source]
就像HttpResponse但使用404狀態碼class HttpResponseForbidden[source]
就像HttpResponse但使用403狀態碼class HttpResponseNotAllowed[source]
像HttpResponse,但使用405狀態碼。第一argumentto構造函數要求准許清單的方法(如(get,後])class HttpResponseGone[source]
就像HttpResponse但使用410狀態碼class HttpResponseServerError[source]
就像HttpResponse但使用500狀態碼
5、模板層
一、模版的執行
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html) from django import template t = template.Template('My name is {{ name }}.') c = template.Context({'name': 'Adrian'}) print t.render(c) import datetime from django import template import DjangoDemo.settings now = datetime.datetime.now() fp = open(settings.BASE_DIR+'/templates/Home/Index.html') t = template.Template(fp.read()) fp.close() html = t.render(template.Context({'current_date': now})) return HttpResponse(html from django.template.loader import get_template from django.template import Context from django.http import HttpResponse import datetime def current_datetime(request): now = datetime.datetime.now() t = get_template('current_datetime.html') html = t.render(Context({'current_date': now})) return HttpResponse(html) return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))
二、模版語言
模板中也有本身的語言,該語言能夠實現數據展現
- {{ 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 }}
三、自定義simple_tag
a、在app中建立templatetags模塊
b、建立任意 .py 文件,如:xx.py
#!/usr/bin/env python #coding:utf-8 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)
c、在使用自定義simple_tag的html文件中導入以前建立的 xx.py 文件名
{% load xx %}
d、使用simple_tag
{% my_simple_time 1 2 3%} {% my_input 'id_username' 'hide'%}
e、在settings中配置當前app,否則django沒法找到自定義的simple_tag
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', )
6、Model 層
Django提供了一個抽象層(「Model」)的構建和管理Web應用程序的數據。
- 每一個模型是一個Python類,子類
d jango.db.models.model
- 模型中的每一個屬性表明一個數據庫字段。
簡單的例子
from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30)
參數與字段
一、models.AutoField 自增列 = int(11) 若是沒有的話,默認會生成一個名稱爲 id 的列,若是要顯示的自定義一個自增列,必須將給列設置爲主鍵 primary_key=True。 2、models.CharField 字符串字段 必須 max_length 參數 三、models.BooleanField 布爾類型=tinyint(1) 不能爲空,Blank=True 四、models.ComaSeparatedIntegerField 用逗號分割的數字=varchar 繼承CharField,因此必須 max_lenght 參數 5、models.DateField 日期類型 date 對於參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次建立添加,以後的更新再也不改變。 6、models.DateTimeField 日期類型 datetime 同DateField的參數 七、models.Decimal 十進制小數類型 = decimal 必須指定整數位max_digits和小數位decimal_places 八、models.EmailField 字符串類型(正則表達式郵箱) =varchar 對字符串進行正則表達式 九、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、ipv四、ipv6 驗證時,會根據設置報錯 14、models.NullBooleanField 容許爲空的布爾類型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 減號、下劃線、字母、數字 18、models.SmallIntegerField 數字 數據庫中的字段有:tinyint、smallint、int、bigint 1九、models.TextField 字符串=longtext 20、models.TimeField 時間 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正則表達式 22、models.BinaryField 二進制 23、models.ImageField 圖片 2四、models.FilePathField 文件
一、null=True 數據庫中字段是否能夠爲空 二、blank=True django的 Admin 中添加數據時是否可容許空值 三、primary_key = False 主鍵,對AutoField設置主鍵後,就會代替原來的自增 id 列 4、auto_now 和 auto_now_add auto_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中字段的顯示名稱 九、name|db_column 數據庫中的字段名稱 十、unique=True 不容許重複 十一、db_index = True 數據庫索引 十二、editable=True 在Admin裏是否可編輯 1三、error_messages=None 錯誤提示 1四、auto_created=False 自動建立 15、help_text 在Admin中提示幫助信息 1六、validators=[] 1七、upload-to
連表結構
- 一對多:models.ForeignKey(其餘表)
- 多對多:models.ManyToManyField(其餘表)
- 一對一:models.OneToOneField(其餘表)
操做表
一、基本操做
# 增 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='nick').delete() # 刪除指定條件的數據 # 改models.Tb1.objects.filter(name='nick').update(gender='0') # 將指定條件的數據更新,均支持 **kwargs obj = models.Tb1.objects.get(id=1) obj.c1 = '111' obj.save() # 修改單條數據
二、進階操做(了不得的雙下劃線)
利用雙下劃線將字段和對應的操做鏈接起來
# 獲取個數 models.Tb1.objects.filter(name='nick').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='nick').order_by('id') # asc models.Tb1.objects.filter(name='nick').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"
三、連表操做(了不得的雙下劃線)
利用雙下劃線和 _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.username class 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.name class UserGroup(models.Model): caption = models.CharField(max_length=64) user_info = models.ManyToManyField('UserInfo') def __unicode__(self): return self.caption class 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.password user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() print user_info_obj.keys() print user_info_obj.values()
# 添加一對多 dic = { "hostname": "名字1", "ip": "192.168.1.1", "user_group_id": 1, # 加對象則爲"user_group" } models.Host.objects.create(**dic) # 正向查一對多 host_obj = models.Host.objects.all() print(type(host_obj), # <class 'django.db.models.query.QuerySet'> host_obj) # <QuerySet [<Host: 名字1>]> for item in host_obj: print(item.hostname) print(item.user_group.caption) print(item.user_group.user_info.values()) # <QuerySet [{'name': 'nick', 'user_type': 1, 'id': 1, 'email': '630571017@qq.com', 'address': '128號'}]> usergroup_obj = models.Host.objects.filter(user_group__caption='標題1') print(usergroup_obj) # 反向查一對多 usergroup_obj = models.UserGroup.objects.get(id=1) print(usergroup_obj.caption) ret = usergroup_obj.host_set.all() # 全部關於id=1的host print(ret) obj = models.UserGroup.objects.filter(host__ip='192.168.1.1').\ values('host__id', 'host__hostname') print(obj) # <QuerySet [{'host__id': 1, 'host__hostname': '名字1'}]>
user_info_obj = models.UserInfo.objects.get(name='nick') user_info_objs = models.UserInfo.objects.all() group_obj = models.UserGroup.objects.get(caption='CTO') 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='CTO') #print user_info_obj.usergroup_set.all().filter(caption='DBA') # 添加多對多 # userinfo_id_1 = models.UserInfo.objects.filter(id=1) # usergroup_id_1 = models.UserGroup.objects.filter(id=1).first() # usergroup_id_1.user_info.add(*userinfo_id_1)
# 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 app1_userinfo where name = %s""", ['nick']) row = cursor.fetchone() print(row)
注意: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')
b、Form上傳文件實例
<form method="post" action="/view1/" enctype="multipart/form-data"> <input type="file" name="ExcelFile" id="id_ExcelFile" /> <input type="submit" value="提交" /> </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
c、ajax上傳文件實例
<div> {{ up.ExcelFile }} <input type="button" id="submitj" value="提交" /> </div> <script src="/static/js/jquery-2.1.4.min.js"></script> <script> $('#submitj').bind("click",function () { var file = $('#id_ExcelFile')[0].files[0]; var form = new FormData(); form.append('ExcelFile', file); $.ajax({ type:'POST', url: '/view1/', data: form, processData: false, // tell jQuery not to process the data contentType: false, // tell jQuery not to set contentType success: function(arg){ console.log(arg); } }) }) </script>
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)
from study1 import forms 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 return render(request, 'file.html', locals())
7、Form
django中的Form通常有兩種功能:
- 輸入html
- 驗證用戶輸入
#!/usr/bin/env python # -*- coding:utf-8 -*- 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): 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, error_messages={'required': u'標題不能爲空', 'min_length': u'標題最少爲5個字符', 'max_length': u'標題最多爲20個字符'}, 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(validators=[mobile_validate, ], error_messages={'required': u'手機不能爲空'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'手機號碼'})) email = forms.EmailField(required=False, error_messages={'required': u'郵箱不能爲空','invalid': u'郵箱格式錯誤'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'郵箱'}))
def publish(request): ret = {'status': False, 'data': '', 'error': '', 'summary': ''} if request.method == 'POST': request_form = PublishForm(request.POST) if request_form.is_valid(): request_dict = request_form.clean() print request_dict ret['status'] = True else: error_msg = request_form.errors.as_json() ret['error'] = json.loads(error_msg) return HttpResponse(json.dumps(ret))
擴展: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"}), }
8、認證系統auth
auth模塊是Django提供的標準權限管理系統,能夠提供用戶身份認證, 用戶組管理,而且能夠和admin模塊配合使用.
在INSTALLED_APPS中添加'django.contrib.auth'使用該APP, auth模塊默認啓用.
model
from django.contrib.auth.models import User # 數據庫中該表名爲auth_user. CREATE TABLE "auth_user" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "password" varchar(128) NOT NULL, "last_login" datetime NULL, "is_superuser" bool NOT NULL, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL, "email" varchar(254) NOT NULL, "is_staff" bool NOT NULL, "is_active" bool NOT NULL, "date_joined" datetime NOT NULL, "username" varchar(30) NOT NULL UNIQUE )
新建用戶
user = User.objects.create_user(username, email, password) user.save() # 不存儲用戶密碼明文而是存儲一個Hash值
認證用戶
from django.contrib.auth import authenticate user = authenticate(username=username, password=password) # 認證用戶的密碼是否有效, 如有效則返回表明該用戶的user對象, 若無效則返回None. # 該方法不檢查is_active標誌位.
修改密碼
user.set_password(new_password) # 如下實例爲先認證經過後才能夠修改密碼 user = auth.authenticate(username=username, password=old_password) if user is not None: user.set_password(new_password) user.save()
登陸
from django.contrib.auth import login # login向session中添加SESSION_KEY, 便於對用戶進行跟蹤: 'login(request, user)' # login不進行認證,也不檢查is_active標誌位 # 實例 user = authenticate(username=username, password=password) if user is not None: if user.is_active: login(request, user)
退出登陸
# logout會移除request中的user信息, 並刷新session from django.contrib.auth import logout def logout_view(request): logout(request)
只容許登陸的用戶訪問
@login_required
修飾器修飾的view函數會先經過session key檢查是否登陸, 已登陸用戶能夠正常的執行操做, 未登陸用戶將被重定向到login_url
指定的位置.
若未指定login_url參數, 則重定向到settings.LOGIN_URL
from django.contrib.auth.decorators import login_required @login_required(login_url='/accounts/login/') def userinfo(request): ... # settings 配置 LOGIN_URL = '/index/' # views @login_required def userinfo(request): ...
9、跨站請求僞造
簡介
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
應用
一、普通表單
veiw中設置返回值: return render_to_response('Account/Login.html',data,context_instance=RequestContext(request)) 或者 return render(request, 'xxx.html', data) html中設置Token: {% csrf_token %}
二、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>
更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
10、分頁
Django內置分頁
Paginator
自定義分頁
#!/usr/bin/env python # _*_coding:utf-8_*_ from django.utils.safestring import mark_safe class PageInfo(object): def __init__(self,current,totalItem,peritems=5): self.__current=current self.__peritems=peritems self.__totalItem=totalItem def From(self): return (self.__current-1)*self.__peritems def To(self): return self.__current*self.__peritems def TotalPage(self): #總頁數 result=divmod(self.__totalItem,self.__peritems) if result[1]==0: return result[0] else: return result[0]+1 def Custompager(baseurl,currentPage,totalpage): #基礎頁,當前頁,總頁數 perPager=11 #總頁數<11 #0 -- totalpage #總頁數>11 #當前頁大於5 currentPage-5 -- currentPage+5 #currentPage+5是否超過總頁數,超過總頁數,end就是總頁數 #當前頁小於5 0 -- 11 begin=0 end=0 if totalpage <= 11: begin=0 end=totalpage else: if currentPage>5: begin=currentPage-5 end=currentPage+5 if end > totalpage: end=totalpage else: begin=0 end=11 pager_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語言
11、Cookice
獲取Cookie:
request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None) 參數: default: 默認值 salt: 加密鹽 max_age: 後臺控制過時時間
設置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: '/' });
12、Session
Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:
- 數據庫(默認)
- 緩存
- 文件
- 緩存+數據庫
- 加密cookie
一、數據庫Session
Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_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. 使用 同上
五、加密cookie Session
a. 配置 settings.py SESSION_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
六、Redis 實現
環境安裝
pip install django-redis pip install django-redis-cache pip install django-redis-sessions
1> 配置django-redis-sessions
在settings.py中配置
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # SESSION_ENGINE = 'redis_sessions.session' SESSION_REDIS_HOST = 'localhost' SESSION_REDIS_PORT = 6379 SESSION_REDIS_DB = 0 SESSION_REDIS_PASSWORD = 'password' SESSION_REDIS_PREFIX = 'session' SESSION_COOKIE_NAME = 'session_name' SESSION_COOKIE_AGE = '60*20' # 超時時間 # If you prefer domain socket connection, you can just add this line instead of SESSION_REDIS_HOST and SESSION_REDIS_PORT. SESSION_REDIS_UNIX_DOMAIN_SOCKET_PATH = '/var/run/redis/redis.sock'
配置完成後可測試以下:
$ pip install django nose redis # Make sure you have redis running on localhost:6379 (poem)[beginman@beginman poem]$ nosetests ---------------------------------------------------------------------- Ran 0 tests in 0.001s OK
2> 配置django-redis-sessions
在settings.py中配置
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": [ "redis://:password@IP0.0.0.0:6379", ], "OPTIONS": { # "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": {"max_connections": 100}, # 鏈接池 } } }
CACHES = { 'default': { 'BACKEND': 'redis_cache.RedisCache', 'LOCATION': '<host>:<port>', 'OPTIONS': { 'DB': 1, 'PASSWORD': '', 'PARSER_CLASS': 'redis.connection.HiredisParser', 'CONNECTION_POOL_CLASS': 'redis.BlockingConnectionPool', 'CONNECTION_POOL_CLASS_KWARGS': { 'max_connections': 50, 'timeout': 20, } }, }, }
3>django實現redis的存取
# Start by importing your default cache: from django.core.cache import cache # Store data under a-unique-key: cache.set('a-unique-key', 'this is a string which will be cached') # Later on you can retrieve it in another function: cache.get('a-unique-key') # Will return None if key is not found in cache # You can specify a default value: cache.get('another-unique-key', 'default value') # You can store multiple values at once: cache.set_many({'a': 1, 'b': 2, 'c': 3}) # And fetch multiple values: cache.get_many(['a', 'b', 'c']) # returns {'a': 1, 'b': 2, 'c': 3} # You can store complex types in the cache: cache.set('a-unique-key', { 'string' : 'this is a string', 'int' : 42, 'list' : [1, 2, 3], 'tuple' : (1, 2, 3), 'dict' : {'A': 1, 'B' : 2}, })
更多:http://niwinz.github.io/django-redis/latest/#_installation
十3、緩存
因爲Django是動態網站,全部每次請求均會去數據進行相應的操做,當程序訪問量大時,耗時必然會更加明顯,最簡單解決方式是使用:緩存,緩存將一個某個views的返回值保存至內存或者memcache中,5分鐘內再有人來訪問時,則再也不去執行view中的操做,而是直接從內存或者Redis中以前緩存的內容拿到,並返回。
Django中提供了6種緩存方式:
- 開發調試
- 內存
- 文件
- 數據庫
- Memcache緩存(python-memcached模塊)
- Memcache緩存(pylibmc模塊)
一、配置
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', ] } }
二、應用
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 %}
更多:猛擊這裏
十4、序列化
關於Django中的序列化主要應用在將數據庫中檢索的數據返回給客戶端用戶,特別的Ajax請求通常返回的爲Json格式。
一、serializers
from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize("json", ret)
二、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)
十5、中間件
django 中的中間件(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對象,則直接將該對象返回給用戶。
自定義中間件
一、建立中間件類
class RequestExeute(object): def process_request(self,request): pass def process_view(self, request, callback, callback_args, callback_kwargs): i =1 pass def process_exception(self, request, exception): pass def process_response(self, request, response): return response
二、註冊中間件
MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'wupeiqi.middleware.auth.RequestExeute', )
十6、信號
Django中提供了「信號調度」,用於在框架執行操做時解耦。通俗來說,就是一些動做發生的時候,信號容許特定的發送者去提醒一些接受者。
一、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內置的信號,僅需註冊指定信號,當程序執行相應操做時,自動觸發註冊函數:
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指上述導入的內容
from django.core.signals import request_finished from django.dispatch import receiver @receiver(request_finished) def my_callback(sender, **kwargs): print("Request finished!")
二、自定義信號
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)
因爲內置信號的觸發者已經集成到Django中,因此其會自動調用,而對於自定義信號則須要開發者在任意位置觸發。
更多:猛擊這裏
十7、admin
django amdin是django提供的一個後臺管理頁面,改管理頁面提供完善的html和css,使得你在經過Model建立完數據庫表以後,就能夠對數據進行增刪改查,而使用django admin 則須要如下步驟:
- 建立後臺管理員
- 配置url
- 註冊和配置django admin後臺管理頁面
一、建立後臺管理員
python manage.py createsuperuser
二、配置後臺管理url
url(r'^admin/', include(admin.site.urls))
三、註冊和配置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)
b、設置數據表名稱
class UserType(models.Model): name = models.CharField(max_length=50) class Meta: verbose_name = '用戶類型' verbose_name_plural = '用戶類型'
c、打開表以後,設定默認顯示,須要在model中做以下配置
class UserType(models.Model): name = models.CharField(max_length=50) def __unicode__(self): return self.name
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
d、爲數據表添加搜索功能
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ('username', 'password', 'email') search_fields = ('username', 'email') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
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') admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset)
更多:http://docs.30c.org/djangobook2/chapter06/