Django

1、Django 簡介

  Django 是一個由 Python 寫成的開放源代碼的 Web 應用框架。它最初是被開發來用於管理勞倫斯出版集團旗下的一些以新聞內容爲主的網站的,便是 CMS(內容管理系統)軟件。並於2005年7月在 BSD 許可證下發布。這套框架是以比利時的吉普賽爵士吉他手 Django Reinhardt 來命名的。因爲 Django 的是在一個快節奏的新聞編輯室環境下開發的,它的目的是使常見的 Web 開發任務,快速和容易。javascript

 

MTV 模式

Django 採用了 MTV 設計模式css

上述圖大概是說:html

  1. URL ( urls.py )請求調度,當有緩存頁面的時候直接返回內容。
  2. 視圖函數( view.py )執行所請求的操做,一般包括讀寫數據庫。
  3. 模型( models.py )定義了 Python 中的數據並與之交互。一般包含在一個關係數據庫( MySQL、PostgreSQL SQLite 等),其餘數據存儲是可能的( XML、文本文件、LDAP、等)。
  4. 請求執行任務後,視圖返回一個 HTTP 響應對象(一般是通過數據處理的一個模板)。可選的:視圖能夠保存一個版本的 HTTP 響應對象,返回攜帶一個時間戳,來告訴瀏覽器這個視圖的更新時間。
  5. 模板一般返回 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')
對應 views 函數接收值

 

二級路由: 那若是映射 url 太多怎麼辦,全寫一個在  urlpatterns 顯得繁瑣,so 二級路由應用而生

複製代碼
# 一級路由規定 app1 開頭的都去 app1.urls 中找
# 二級在詳細規定對應 views 函數

# 一級
urlpatterns = [
    url(r'^app1/', include('app1.urls')),
]

# 二級
urlpatterns = [
    url(r'^1$', views.manage1),
]
複製代碼

 

二、Django是如何處理一個請求

當用戶請求從您的 Django 的網站頁面,這是該系統遵循以肯定哪些 Python 代碼執行的算法:

  1. Django 請求是 URL 配置模塊配置。一般經過值 ROOT_URLCONF 設置,但若是傳入 HttpRequest 對象具備 urlconf 屬性(由中間件設置),它的值將代替的可使用  ROOT_URLCONF 的設置。
  2. Django 的負載是 Python 模塊並尋找變量 urlpatterns。這是一個 django.conf.urls.url() 實例。
  3. Django 的貫穿每一個 URL 模式,從而,在所請求的 URL 匹配的第一個中止。
  4. 一旦某個正則表達式相匹配,就運行相對應的視圖函數(或基於類的視圖)。該視圖被傳遞如下參數:
    • HttpRequest 對象。
    • 若是匹配的正則表達式沒有返回命名組,而後從正則表達式比賽是做爲位置參數。
    • 關鍵詞參數是由由正則表達式匹配的任何命名組,由指定的可選參數的任何覆蓋的 kwargs參數 django.conf.urls.url()
  5. 若是沒有正則表達式匹配,或者若是一個異常在這個過程當中的任何一點時提出,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配置解析器遵循算法,相對於正則表達式命名組與非命名組:

  1. 若是有任何命名參數,它會使用這些,而忽略非命名參數。
  2. 不然,它會經過全部非命名參數做爲位置參數。

在這兩種狀況下,被賦予按任何額外的關鍵字參數傳遞額外的選項來查看功能也將被傳遞給視圖

 

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( requesttemplate_namecontext=Nonecontent_type=Nonestatus=Noneusing=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_namecontext=Nonecontent_type=Nonestatus=Noneusing=None)[source]

 這個和  render() 差很少,不推薦,在將來可能廢棄掉

 

redirect()

 redirect(topermanent=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、模板層

  做爲一個Web框架,Django 須要模板。模板包含所需的 HTML 輸出靜態部分以及動態內容插入。

一、模版的執行

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',
)
View Code

 

 

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)
F & Q
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("""SELECT * from app1_userinfo where name = %s""", ['nick'])
    row = cursor.fetchone()
    print(row)
Django 執行原生SQL

注意: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 Code

b、Form上傳文件實例

       <form method="post" action="/view1/" enctype="multipart/form-data">
           <input type="file" name="ExcelFile" id="id_ExcelFile" />
           <input type="submit" value="提交" />
       </form>
HTML
class FileForm(forms.Form):
    ExcelFile = forms.FileField()
Form
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)
models
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
View

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>
HTML
class FileForm(forms.Form):
    ExcelFile = forms.FileField()
Form
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)
models
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())
View

 

 

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'郵箱'}))
Form
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))
View Code

擴展: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

 

 

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))
view.py
# 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>
text.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")
 
        ...
View Code

二、緩存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. 使用
 
    同上
View Code

三、文件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. 使用
 
    同上
View Code

四、緩存+數據庫Session

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

五、加密cookie Session

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

更多參考:猛擊這裏 和 猛擊這裏

擴展: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,
            }
        },
    },
}
View Code
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
View Code

b、內存

# 此緩存將內容保存至內存的變量中
    # 配置:
        CACHES = {
            'default': {
                'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
                'LOCATION': 'unique-snowflake',
            }
        }

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

c、文件

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

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

d、數據庫

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

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

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

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',
            ]
        }
    }
View Code

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',
            ]
        }
    }
View Code

 

二、應用

a、 全站使用

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

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

    CACHE_MIDDLEWARE_ALIAS = ""
    CACHE_MIDDLEWARE_SECONDS = ""
    CACHE_MIDDLEWARE_KEY_PREFIX = ""
View Code

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)),
        ]
View Code

c、局部視圖使用

a. 引入TemplateTag

        {% load cache %}

    b. 使用緩存

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

更多:猛擊這裏

 

 

十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) 
View Code

 

 

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

二、自定義信號

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)
View Code
b、設置數據表名稱
class UserType(models.Model):
    name = models.CharField(max_length=50)
  
    class Meta:
        verbose_name = '用戶類型'
        verbose_name_plural = '用戶類型'
View Code
c、打開表以後,設定默認顯示,須要在model中做以下配置
class UserType(models.Model):
    name = models.CharField(max_length=50)
  
    def __unicode__(self):
        return self.name
View Code
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)
View Code
d、爲數據表添加搜索功能
from django.contrib import admin
  
from app01 import  models
  
class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')
    search_fields = ('username', 'email')
  
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
View Code
e、添加快速過濾
from django.contrib import admin
  
from app01 import  models
  
class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')
    search_fields = ('username', 'email')
    list_filter = ('username', 'email')
      
  
  
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
View Code

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

相關文章
相關標籤/搜索