Django 快速指南



Django - 基礎

Django 是一個高階 Python Web 框架,它鼓勵快速開發和簡潔、實用的設計。Django 使構建更好的 Web 應用更加容易,速度更快,程式碼更少。

注意 − Django 是 Django 軟體基金會的註冊商標,並根據 BSD 許可證授權。

Django 的歷史

  • 2003 − 由 Adrian Holovaty 和 Simon Willison 在 Lawrence Journal-World 報社啟動的一個內部專案。

  • 2005 − 2005 年 7 月釋出,並以爵士吉他手 Django Reinhardt 的名字命名。

  • 2005 − 足夠成熟,可以處理多個高流量站點。

  • 現在 − Django 現在是一個開源專案,擁有來自世界各地的貢獻者。

Django – 設計理念

Django 具有以下設計理念:

  • 鬆散耦合 − Django 旨在使其堆疊的每個元素彼此獨立。

  • 程式碼更少 − 更少的程式碼,從而實現快速開發。

  • 不要重複自己 (DRY) − 每一件事都應該只在一個地方開發,而不是一遍遍重複。

  • 快速開發 − Django 的理念是盡其所能促進超快速開發。

  • 簡潔的設計 − Django 嚴格地在自己的程式碼中保持簡潔的設計,並使其易於遵循最佳 Web 開發實踐。

Django 的優勢

以下是使用 Django 的一些優勢:

  • 物件關係對映 (ORM) 支援 − Django 在資料模型和資料庫引擎之間架起了一座橋樑,並支援大量資料庫系統,包括 MySQL、Oracle、Postgres 等。Django 還透過 Django-nonrel 分支支援 NoSQL 資料庫。目前,唯一支援的 NoSQL 資料庫是 MongoDB 和 Google App Engine。

  • 多語言支援 − Django 透過其內建的國際化系統支援多語言網站。因此,您可以開發支援多種語言的網站。

  • 框架支援 − Django 內建支援 Ajax、RSS、快取和各種其他框架。

  • 管理 GUI − Django 提供了一個易於使用的使用者介面,用於執行管理活動。

  • 開發環境 − Django 自帶一個輕量級的 Web 伺服器,以方便端到端應用程式的開發和測試。

Django - 概述

您可能已經知道,Django 是一個 Python Web 框架。與大多數現代框架一樣,Django 支援 MVC 模式。首先,讓我們看看什麼是模型-檢視-控制器 (MVC) 模式,然後我們將瞭解 Django 的模型-檢視-模板 (MVT) 模式的具體內容。

MVC 模式

當談到提供 UI(Web 或桌面)的應用程式時,我們通常會談到 MVC 架構。顧名思義,MVC 模式基於三個元件:模型、檢視和控制器。點選此處檢視我們的 MVC 教程 以瞭解更多資訊。

DJANGO MVC - MVT 模式

模型-檢視-模板 (MVT) 與 MVC 略有不同。事實上,這兩種模式的主要區別在於 Django 本身負責控制器部分(控制模型和檢視之間互動的軟體程式碼),留給我們的是模板。模板是一個混合了 Django 模板語言 (DTL) 的 HTML 檔案。

下圖說明了 MVT 模式的各個元件如何相互互動以響應使用者請求:

DJANGO MVC - MVT Pattern

開發人員提供模型、檢視和模板,然後將其對映到 URL,Django 就會發揮其魔力,將其提供給使用者。

Django - 環境配置

Django 開發環境包括安裝和設定 Python、Django 和資料庫系統。由於 Django 處理 Web 應用程式,因此值得一提的是,您還需要設定 Web 伺服器。

步驟 1 – 安裝 Python

Django 是用 100% 純 Python 程式碼編寫的,因此您需要在系統上安裝 Python。最新的 Django 版本需要 Python 2.6.5 或更高版本(對於 2.6.x 分支)或 2.7.3 以上版本(對於 2.7.x 分支)。

如果您使用的是最新的 Linux 或 Mac OS X 發行版,那麼您可能已經安裝了 Python。您可以透過在命令提示符下鍵入 *python* 命令來驗證它。如果您看到類似這樣的內容,則表示已安裝 Python。

$ python
Python 2.7.5 (default, Jun 17 2014, 18:11:42)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2

否則,您可以從連結https://python.club.tw/downloads/下載並安裝最新版本的 Python。

步驟 2 - 安裝 Django

安裝 Django 非常容易,但安裝所需的步驟取決於您的作業系統。由於 Python 是一種平臺無關的語言,因此 Django 有一個可在任何地方使用的軟體包,無論您的作業系統是什麼。

您可以從連結https://www.djangoproject.com/download/下載最新版本的 Django。

UNIX/Linux 和 Mac OS X 安裝

如果您執行的是 Linux 或 Mac OS 系統,則有兩種安裝 Django 的方法:

  • 您可以使用作業系統的包管理器,或者使用 easy_install 或 pip(如果已安裝)。

  • 使用之前下載的官方存檔手動安裝。

我們將介紹第二種方法,因為第一種方法取決於您的作業系統發行版。如果您決定選擇第一種方法,請注意您正在安裝的 Django 版本。

假設您從上面的連結獲得了存檔,它應該類似於 Django-x.xx.tar.gz

解壓縮並安裝。

$ tar xzvf Django-x.xx.tar.gz
$ cd Django-x.xx
$ sudo python setup.py install

您可以透過執行以下命令來測試您的安裝:

$ django-admin.py --version

如果螢幕上打印出當前版本的 Django,則一切設定完畢。

注意 − 對於某些版本的 Django,它將是 django-admin,“.py” 已刪除。

Windows 安裝

我們假設您已經在計算機上安裝了 Django 存檔和 python。

首先,PATH 驗證。

在某些版本的 Windows(Windows 7)上,您可能需要確保 Path 系統變數包含以下路徑 `C:\Python27\;C:\Python27\Lib\site-packages\django\bin\`,當然這取決於您的 Python 版本。

然後,解壓縮並安裝 Django。

c:\>cd c:\Django-x.xx

接下來,透過執行以下命令安裝 Django,在 Windows shell “cmd” 中您需要管理員許可權:

c:\Django-x.xx>python setup.py install

要測試您的安裝,請開啟命令提示符並鍵入以下命令:

c:\>django-admin.py --version

如果螢幕上打印出當前版本的 Django,則一切設定完畢。

或者

啟動“cmd”提示符並鍵入 python,然後:

c:\> python
>>> import django
>>> print django.get_version()

步驟 3 – 資料庫設定

Django 支援多種主要的資料庫引擎,您可以根據自己的喜好設定其中任何一個。

您可以參考相應的文件來安裝和配置您選擇的資料庫。

注意 − 5 和 6 是 NoSQL 資料庫。

步驟 4 – Web 伺服器

Django 自帶一個輕量級的 Web 伺服器,用於開發和測試應用程式。此伺服器已預配置為與 Django 一起工作,更重要的是,它會在您修改程式碼時重新啟動。

但是,Django 也支援 Apache 和其他流行的 Web 伺服器,例如 Lighttpd。在接下來的章節中,我們將透過不同的示例討論這兩種方法。

Django - 建立專案

現在我們已經安裝了 Django,讓我們開始使用它。在 Django 中,您要建立的每個 Web 應用都稱為專案;專案是由應用組成的。應用是一組依賴於 MVT 模式的程式碼檔案。例如,假設我們要構建一個網站,網站就是我們的專案,而論壇、新聞、聯絡引擎就是應用。這種結構使得在專案之間移動應用變得更容易,因為每個應用都是獨立的。

建立專案

無論您使用的是 Windows 還是 Linux,只需獲取終端或 **cmd** 提示符並導航到您希望建立專案的目錄,然後使用此程式碼:

$ django-admin startproject myproject

這將建立一個“myproject”資料夾,其結構如下:

myproject/
   manage.py
   myproject/
      __init__.py
      settings.py
      urls.py
      wsgi.py

專案結構

“myproject”資料夾只是您的專案容器,它實際上包含兩個元素:

  • **manage.py** − 此檔案類似於您的專案本地 django-admin,用於透過命令列與您的專案進行互動(啟動開發伺服器、同步資料庫……)。要獲取可透過 manage.py 訪問的命令的完整列表,您可以使用以下程式碼:

$ python manage.py help
  • **“myproject”子資料夾** − 此資料夾是專案的實際 Python 包。它包含四個檔案:

    • **__init__.py** − 僅供 Python 使用,將此資料夾視為包。

    • **settings.py** − 顧名思義,這是您的專案設定。

    • **urls.py** − 專案的所有連結以及要呼叫的函式。類似於專案的目錄。

    • **wsgi.py** − 如果您需要透過 WSGI 部署專案。

設定您的專案

您的專案設定在子資料夾 myproject/settings.py 中。以下是一些您可能需要設定的重要選項:

DEBUG = True

此選項允許您設定專案是處於除錯模式還是非除錯模式。除錯模式允許您獲取有關專案錯誤的更多資訊。切勿為生產專案將其設定為“True”。但是,如果您希望 Django 輕量級伺服器提供靜態檔案,則必須將其設定為“True”。僅在開發模式下這樣做。

DATABASES = {
   'default': {
      'ENGINE': 'django.db.backends.sqlite3',
      'NAME': 'database.sql',
      'USER': '',
      'PASSWORD': '',
      'HOST': '',
      'PORT': '',
   }
}

資料庫在“Database”字典中設定。上面的示例是針對 SQLite 引擎的。如前所述,Django 還支援:

  • MySQL (django.db.backends.mysql)
  • PostGreSQL (django.db.backends.postgresql_psycopg2)
  • Oracle (django.db.backends.oracle) 和 NoSQL 資料庫
  • MongoDB (django_mongodb_engine)

在設定任何新的引擎之前,請確保已安裝正確的資料庫驅動程式。

您還可以設定其他選項,例如:TIME_ZONE、LANGUAGE_CODE、TEMPLATE……

現在您的專案已建立並配置完畢,請確保它正在執行:

$ python manage.py runserver

執行上述程式碼後,您將看到類似以下內容:

Validating models...

0 errors found
September 03, 2015 - 11:41:50
Django version 1.6.11, using settings 'myproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Django - 應用生命週期

專案是由許多應用組成的。每個應用都有一個目標,並且可以在另一個專案中重複使用,例如網站上的聯絡表單可以是一個應用,並且可以重複用於其他專案。將其視為專案的模組。

建立應用

我們假設您位於專案資料夾中。在我們的主“myproject”資料夾中,與 manage.py 相同的資料夾:

$ python manage.py startapp myapp

您剛剛建立了myapp應用程式,就像專案一樣,Django會建立一個包含應用程式結構的“myapp”資料夾:

myapp/
   __init__.py
   admin.py
   models.py
   tests.py
   views.py
  • __init__.py − 確保Python將此資料夾視為一個包。

  • admin.py − 此檔案幫助您在管理介面中修改應用程式。

  • models.py − 這是儲存所有應用程式模型的地方。

  • tests.py − 這是存放單元測試的地方。

  • views.py − 這是存放應用程式檢視的地方。

讓專案瞭解您的應用程式

在這個階段,我們有了“myapp”應用程式,現在我們需要將其註冊到我們的Django專案“myproject”中。為此,請更新專案`settings.py`檔案中的`INSTALLED_APPS`元組(新增您的應用程式名稱):

INSTALLED_APPS = (
   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'myapp',
)

Django - 管理介面

Django提供了一個現成的使用者介面,用於執行管理活動。我們都知道管理介面對於Web專案的重要性。Django會根據您的專案模型自動生成管理UI。

啟動管理介面

管理介面依賴於`django.contrib`模組。要使其正常工作,您需要確保在`myproject/settings.py`檔案的`INSTALLED_APPS`和`MIDDLEWARE_CLASSES`元組中匯入了某些模組。

對於`INSTALLED_APPS`,請確保您擁有:

INSTALLED_APPS = (
   'django.contrib.admin',
   'django.contrib.auth',
   'django.contrib.contenttypes',
   'django.contrib.sessions',
   'django.contrib.messages',
   'django.contrib.staticfiles',
   'myapp',
)

對於`MIDDLEWARE_CLASSES`:

MIDDLEWARE_CLASSES = (
   'django.contrib.sessions.middleware.SessionMiddleware',
   'django.middleware.common.CommonMiddleware',
   'django.middleware.csrf.CsrfViewMiddleware',
   'django.contrib.auth.middleware.AuthenticationMiddleware',
   'django.contrib.messages.middleware.MessageMiddleware',
   'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

在啟動伺服器之前,要訪問您的管理介面,您需要初始化資料庫:

$ python manage.py migrate

`syncdb`將根據您的資料庫型別建立必要的表或集合,這是管理介面執行所必需的。即使您沒有超級使用者,系統也會提示您建立一個。

如果您已經有超級使用者或忘記了它,您可以始終使用以下程式碼建立一個:

$ python manage.py createsuperuser

現在要啟動管理介面,我們需要確保我們已為管理介面配置了一個URL。開啟`myproject/urls.py`,您應該看到類似以下內容:

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
   # Examples:
   # url(r'^$', 'myproject.views.home', name = 'home'),
   # url(r'^blog/', include('blog.urls')),

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

現在只需執行伺服器。

$ python manage.py runserver

您的管理介面可以透過以下地址訪問:http://127.0.0.1:8000/admin/

Admin Interface

使用超級使用者帳戶連線後,您將看到以下螢幕:

Super User Account

該介面允許您管理Django組和使用者,以及應用程式中所有已註冊的模型。該介面至少允許您對模型執行“CRUD”(建立、讀取、更新、刪除)操作。

Django - 建立檢視

檢視函式(簡稱“檢視”)只是一個Python函式,它接收一個Web請求並返回一個Web響應。此響應可以是網頁的HTML內容、重定向、404錯誤、XML文件、影像等。例如:您可以使用檢視來建立網頁,請注意,您需要將檢視與URL關聯才能將其顯示為網頁。

在Django中,檢視必須在應用程式的`views.py`檔案中建立。

簡單的檢視

我們將在myapp中建立一個簡單的檢視,顯示“歡迎使用我的應用程式!”

檢視以下檢視:

from django.http import HttpResponse

def hello(request):
   text = """<h1>welcome to my app !</h1>"""
   return HttpResponse(text)

在此檢視中,我們使用`HttpResponse`渲染HTML(您可能已經注意到,我們已在檢視中硬編碼HTML)。要將此檢視顯示為頁面,我們只需要將其對映到URL(這將在後續章節中討論)。

我們之前使用`HttpResponse`在檢視中渲染HTML。這不是渲染頁面的最佳方法。Django支援MVT模式,因此要使前面的檢視類似於Django-MVT,我們需要:

一個模板:`myapp/templates/hello.html`

現在我們的檢視將如下所示:

from django.shortcuts import render

def hello(request):
   return render(request, "myapp/template/hello.html", {})

檢視還可以接受引數:

from django.http import HttpResponse

def hello(request, number):
   text = "<h1>welcome to my app number %s!</h1>"% number
   return HttpResponse(text)

連結到URL時,頁面將顯示作為引數傳遞的數字。請注意,引數將透過URL傳遞(在下一章中討論)。

Django - URL對映

現在我們有了前面章節中解釋的工作檢視。我們想透過URL訪問該檢視。Django有自己的URL對映方式,這是透過編輯專案`urls.py`檔案**(myproject/urls.py)**來完成的。`urls.py`檔案如下所示:

from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
   #Examples
   #url(r'^$', 'myproject.view.home', name = 'home'),
   #url(r'^blog/', include('blog.urls')),

   url(r'^admin', include(admin.site.urls)),
)

當用戶請求Web應用程式上的頁面時,Django控制器接管以透過`urls.py`檔案查詢相應的檢視,然後返回HTML響應或404未找到錯誤(如果未找到)。在`urls.py`中,最重要的內容是**“urlpatterns”**元組。您在此定義URL和檢視之間的對映。URL模式中的對映是一個元組,例如:

from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
   #Examples
   #url(r'^$', 'myproject.view.home', name = 'home'),
   #url(r'^blog/', include('blog.urls')),

   url(r'^admin', include(admin.site.urls)),
   url(r'^hello/', 'myapp.views.hello', name = 'hello'),
)

標記行將URL“/home”對映到`myapp/views.py`檔案中建立的`hello`檢視。如上所示,對映由三個元素組成:

  • 模式 − 與您想要解析和對映的URL匹配的正則表示式。Python 're' 模組可以使用的任何內容都符合模式的條件(當您想透過URL傳遞引數時很有用)。

  • 檢視的Python路徑 − 與匯入模組時相同。

  • 名稱 − 為了執行URL反轉,您需要使用上面示例中所示的命名URL模式。完成後,只需啟動伺服器即可透過:http://127.0.0.1/hello訪問您的檢視。

組織您的URL

到目前為止,我們已在“myprojects/urls.py”檔案中建立了URL,但是如前所述,關於Django和建立應用程式的最佳之處在於能夠在不同的專案中重用應用程式。如果您將所有URL都儲存在“projecturls.py”檔案中,那麼很容易看出問題所在。因此,最佳實踐是為每個應用程式建立一個“urls.py”,並將其包含在我們的主要專案urls.py檔案中(我們之前包含了管理介面的admin URLs)。

Organize URLs

如何操作?

我們需要使用以下程式碼在myapp中建立一個urls.py檔案:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('', url(r'^hello/', 'myapp.views.hello', name = 'hello'),)

然後`myproject/urls.py`將更改為以下內容:

from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
   #Examples
   #url(r'^$', 'myproject.view.home', name = 'home'),
   #url(r'^blog/', include('blog.urls')),

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

我們包含了myapp應用程式的所有URL。“home.html”之前透過“/hello”訪問,現在是“/myapp/hello”,這是Web應用程式更好、更容易理解的結構。

Myproject

現在假設我們在myapp中還有另一個檢視“morning”,並且我們想在`myapp/urls.py`中對映它,那麼我們將更改`myapp/urls.py`為:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('',
   url(r'^hello/', 'myapp.views.hello', name = 'hello'),
   url(r'^morning/', 'myapp.views.morning', name = 'morning'),
)

這可以重構為:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('myapp.views',
   url(r'^hello/', 'hello', name = 'hello'),
   url(r'^morning/', 'morning', name = 'morning'),)

如您所見,我們現在使用`urlpatterns`元組的第一個元素。當您想更改應用程式名稱時,這很有用。

URL Patterns

向檢視傳送引數

我們現在知道如何對映URL,如何組織它們,現在讓我們看看如何向檢視傳送引數。一個經典的示例是文章示例(您想透過“/articles/article_id”訪問一篇文章)。

傳遞引數是透過在URL模式中使用**正則表示式**捕獲它們來完成的。如果我們在“myapp/views.py”中有以下檢視:

from django.shortcuts import render
from django.http import HttpResponse

def hello(request):
   return render(request, "hello.html", {})

def viewArticle(request, articleId):
   text = "Displaying article Number : %s"%articleId
   return HttpResponse(text)

我們想在`myapp/urls.py`中對映它,以便我們可以透過“/myapp/article/articleId”訪問它,我們需要在“myapp/urls.py”中新增以下內容:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('myapp.views',
   url(r'^hello/', 'hello', name = 'hello'),
   url(r'^morning/', 'morning', name = 'morning'),
   url(r'^article/(\d+)/', 'viewArticle', name = 'article'),)

當Django看到url:“/myapp/article/42”時,它將引數'42'傳遞給`viewArticle`檢視,在您的瀏覽器中,您應該得到以下結果:

Passing parameters to viewArticle

請注意,此處引數的順序很重要。假設我們想要一年中一個月的文章列表,讓我們新增一個`viewArticles`檢視。我們的`views.py`變為:

from django.shortcuts import render
from django.http import HttpResponse

def hello(request):
   return render(request, "hello.html", {})

def viewArticle(request, articleId):
   text = "Displaying article Number : %s"%articleId
   return HttpResponse(text)

def viewArticles(request, month, year):
   text = "Displaying articles of : %s/%s"%(year, month)
   return HttpResponse(text)

相應的**urls.py**檔案將如下所示:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('myapp.views',
   url(r'^hello/', 'hello', name = 'hello'),
   url(r'^morning/', 'morning', name = 'morning'),
   url(r'^article/(\d+)/', 'viewArticle', name = 'article'),
   url(r'^articles/(\d{2})/(\d{4})', 'viewArticles', name = 'articles'),)

現在當您訪問“/myapp/articles/12/2006/”時,您將得到'Displaying articles of: 2006/12',但如果您反轉引數,您將不會得到相同的結果。

Displaying Articles

為避免這種情況,可以將URL引數連結到檢視引數。為此,我們的**urls.py**將變為:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('myapp.views',
   url(r'^hello/', 'hello', name = 'hello'),
   url(r'^morning/', 'morning', name = 'morning'),
   url(r'^article/(\d+)/', 'viewArticle', name = 'article'),
   url(r'^articles/(?P\d{2})/(?P\d{4})', 'viewArticles', name = 'articles'),)

Django - 模板系統

Django允許分離Python和HTML,Python放在檢視中,HTML放在模板中。為了將兩者關聯起來,Django依賴於render函式和Django模板語言。

Render函式

此函式接受三個引數:

  • 請求 − 初始請求。

  • 模板路徑 − 這是相對於專案`settings.py`變數中的`TEMPLATE_DIRS`選項的相對路徑。

  • 引數字典 − 包含模板中所需所有變數的字典。可以建立此變數,也可以使用`locals()`傳遞在檢視中宣告的所有區域性變數。

Django模板語言 (DTL)

Django的模板引擎提供了一種小型語言來定義應用程式的使用者介面層。

顯示變數

變數如下所示:{{variable}}。模板會將變數替換為檢視在render函式的第三個引數中傳送的變數。讓我們更改`hello.html`以顯示今天的日期:

hello.html

<html>
   
   <body>
      Hello World!!!<p>Today is {{today}}</p>
   </body>
   
</html>

然後我們的檢視將更改為:

def hello(request):
   today = datetime.datetime.now().date()
   return render(request, "hello.html", {"today" : today})

訪問URL/myapp/hello後,我們將得到以下輸出:

Hello World!!!
Today is Sept. 11, 2015

您可能已經注意到,如果變數不是字串,Django將使用`__str__`方法來顯示它;並且使用相同的原理,您可以像在Python中一樣訪問物件屬性。例如:如果我們想顯示日期年份,我的變數將是:{{today.year}}。

過濾器

它們幫助您在顯示時修改變數。過濾器的結構如下所示:{{var|filters}}。

一些例子

  • {{string|truncatewords:80}} − 此過濾器將截斷字串,因此您只會看到前80個單詞。

  • {{string|lower}} − 將字串轉換為小寫。

  • {{string|escape|linebreaks}} − 跳脫字元串內容,然後將換行符轉換為標籤。

您還可以為變數設定預設值。

標籤

標籤允許您執行以下操作:if條件、for迴圈、模板繼承等等。

if標籤

就像在Python中一樣,您可以在模板中使用if、else和elif:

<html>
   <body>
   
      Hello World!!!<p>Today is {{today}}</p>
      We are
      {% if today.day == 1 %}
      
      the first day of month.
      {% elif today.day == 30 %}
      
      the last day of month.
      {% else %}
      
      I don't know.
      {%endif%}
      
   </body>
</html>

在這個新的模板中,根據一天中的日期,模板將渲染某個值。

for標籤

就像'if'一樣,我們有'for'標籤,它的工作方式與Python中的完全相同。讓我們更改`hello`檢視以將列表傳輸到我們的模板:

def hello(request):
   today = datetime.datetime.now().date()
   
   daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
   return render(request, "hello.html", {"today" : today, "days_of_week" : daysOfWeek})

使用{{ for }}顯示該列表的模板:

<html>
   <body>
      
      Hello World!!!<p>Today is {{today}}</p>
      We are
      {% if today.day == 1 %}
      
      the first day of month.
      {% elif today.day == 30 %}
      
      the last day of month.
      {% else %}
      
      I don't know.
      {%endif%}
      
      <p>
         {% for day in days_of_week %}
         {{day}}
      </p>
		
      {% endfor %}
      
   </body>
</html>

我們應該得到類似以下內容:

Hello World!!!
Today is Sept. 11, 2015
We are I don't know.
Mon
Tue
Wed
Thu
Fri
Sat
Sun

Block和Extend標籤

如果沒有模板繼承,模板系統就不完整。這意味著在設計模板時,您應該有一個帶有空洞的主模板,子模板將根據其自身的需求填充這些空洞,例如頁面可能需要為選定的選項卡使用特殊的css。

讓我們更改`hello.html`模板以繼承自`main_template.html`。

main_template.html

<html>
   <head>
      
      <title>
         {% block title %}Page Title{% endblock %}
      </title>
      
   </head>
	
   <body>
   
      {% block content %}
         Body content
      {% endblock %}
      
   </body>
</html>

hello.html

{% extends "main_template.html" %}
{% block title %}My Hello Page{% endblock %}
{% block content %}

Hello World!!!<p>Today is {{today}}</p>
We are
{% if today.day == 1 %}

the first day of month.
{% elif today.day == 30 %}

the last day of month.
{% else %}

I don't know.
{%endif%}

<p>
   {% for day in days_of_week %}
   {{day}}
</p>

{% endfor %}
{% endblock %}

在上面的示例中,呼叫/myapp/hello時,我們將仍然得到與之前相同的結果,但現在我們依賴於extends和block來重構我們的程式碼:

在 `main_template.html` 中,我們使用 `block` 標籤定義塊。`title` 塊將包含頁面標題,`content` 塊將包含頁面主要內容。在 `home.html` 中,我們使用 `extends` 繼承 `main_template.html`,然後填充上面定義的塊(`content` 和 `title`)。

註釋標籤

註釋標籤用於在模板中定義註釋,而不是 HTML 註釋,它們不會出現在 HTML 頁面中。這對於文件編寫或僅僅註釋程式碼行非常有用。

Django - 模型

模型是一個類,它代表資料庫中的表或集合,其中類的每個屬性都是表或集合的欄位。模型定義在 `app/models.py` 中(在我們的示例中:`myapp/models.py`)。

建立模型

以下是一個作為示例建立的 Dreamreal 模型:

from django.db import models

class Dreamreal(models.Model):

   website = models.CharField(max_length = 50)
   mail = models.CharField(max_length = 50)
   name = models.CharField(max_length = 50)
   phonenumber = models.IntegerField()

   class Meta:
      db_table = "dreamreal"

每個模型都繼承自 `django.db.models.Model`。

我們的類有 4 個屬性(3 個 `CharField` 和 1 個 `IntegerField`),這些將成為表字段。

`Meta` 類帶有 `db_table` 屬性,允許我們定義實際的表或集合名稱。Django 會自動命名錶或集合:`myapp_modelName`。此類將允許您強制將表名設定為您喜歡的名稱。

建立模型後,您需要 Django 生成實際的資料庫:

$python manage.py syncdb

資料操作 (CRUD)

讓我們建立一個 "crudops" 檢視來檢視如何對模型執行 CRUD 操作。我們的 `myapp/views.py` 將如下所示:

`myapp/views.py`

from myapp.models import Dreamreal
from django.http import HttpResponse

def crudops(request):
   #Creating an entry
   
   dreamreal = Dreamreal(
      website = "www.polo.com", mail = "sorex@polo.com", 
      name = "sorex", phonenumber = "002376970"
   )
   
   dreamreal.save()
   
   #Read ALL entries
   objects = Dreamreal.objects.all()
   res ='Printing all Dreamreal entries in the DB : <br>'
   
   for elt in objects:
      res += elt.name+"<br>"
   
   #Read a specific entry:
   sorex = Dreamreal.objects.get(name = "sorex")
   res += 'Printing One entry <br>'
   res += sorex.name
   
   #Delete an entry
   res += '<br> Deleting an entry <br>'
   sorex.delete()
   
   #Update
   dreamreal = Dreamreal(
      website = "www.polo.com", mail = "sorex@polo.com", 
      name = "sorex", phonenumber = "002376970"
   )
   
   dreamreal.save()
   res += 'Updating entry<br>'
   
   dreamreal = Dreamreal.objects.get(name = 'sorex')
   dreamreal.name = 'thierry'
   dreamreal.save()
   
   return HttpResponse(res)

其他資料操作

讓我們探索一下我們可以在模型上執行的其他操作。請注意,CRUD 操作是在模型例項上執行的,現在我們將直接使用表示模型的類。

讓我們在 **`myapp/views.py`** 中建立一個 'datamanipulation' 檢視。

from myapp.models import Dreamreal
from django.http import HttpResponse

def datamanipulation(request):
   res = ''
   
   #Filtering data:
   qs = Dreamreal.objects.filter(name = "paul")
   res += "Found : %s results<br>"%len(qs)
   
   #Ordering results
   qs = Dreamreal.objects.order_by("name")
   
   for elt in qs:
      res += elt.name + '<br>'
   
   return HttpResponse(res)

模型關聯

Django ORM 提供了三種關聯模型的方法:

我們將在這裡看到的第一個案例是一對多關係。正如你在上面的例子中看到的,Dreamreal 公司可以擁有多個線上網站。定義這種關係是透過使用 `django.db.models.ForeignKey` 來完成的:

`myapp/models.py`

from django.db import models

class Dreamreal(models.Model):
   website = models.CharField(max_length = 50)
   mail = models.CharField(max_length = 50)
   name = models.CharField(max_length = 50)
   phonenumber = models.IntegerField()
   online = models.ForeignKey('Online', default = 1)
   
   class Meta:
      db_table = "dreamreal"

class Online(models.Model):
      domain = models.CharField(max_length = 30)
   
   class Meta:
      db_table = "online"

正如你在我們更新後的 `myapp/models.py` 中看到的,我們添加了 `online` 模型並將其與我們的 `Dreamreal` 模型關聯。

讓我們透過 `manage.py shell` 檢查這一切是如何工作的:

首先,讓我們在 Django shell 中建立一些公司(Dreamreal 條目)進行測試:

$python manage.py shell

>>> from myapp.models import Dreamreal, Online
>>> dr1 = Dreamreal()
>>> dr1.website = 'company1.com'
>>> dr1.name = 'company1'
>>> dr1.mail = 'contact@company1'
>>> dr1.phonenumber = '12345'
>>> dr1.save()
>>> dr2 = Dreamreal()
>>> dr1.website = 'company2.com'
>>> dr2.website = 'company2.com'
>>> dr2.name = 'company2'
>>> dr2.mail = 'contact@company2'
>>> dr2.phonenumber = '56789'
>>> dr2.save()

現在是一些託管域名:

>>> on1 = Online()
>>> on1.company = dr1
>>> on1.domain = "site1.com"
>>> on2 = Online()
>>> on2.company = dr1
>>> on2.domain = "site2.com"
>>> on3 = Online()
>>> on3.domain = "site3.com"
>>> dr2 = Dreamreal.objects.all()[2]
>>> on3.company = dr2
>>> on1.save()
>>> on2.save()
>>> on3.save()

從線上域名訪問託管公司(Dreamreal 條目)的屬性很簡單:

>>> on1.company.name

如果我們想知道 Dreamreal 中所有由公司託管的線上域名,我們將使用以下程式碼:

>>> dr1.online_set.all()

要獲取 QuerySet,請注意我們之前看到的所有操作方法(`filter`、`all`、`exclude`、`order_by`……)。

您還可以訪問關聯模型屬性進行過濾操作,例如,您想獲取 Dreamreal 名稱包含“company”的所有線上域名:

>>> Online.objects.filter(company__name__contains = 'company'

**注意** - 此類查詢僅支援 SQL 資料庫。它不適用於不存在連線且有兩個下劃線的非關係資料庫。

但這並不是關聯模型的唯一方法,您還可以使用 `OneToOneField`,這是一種保證兩個物件之間的關係唯一的關聯。如果我們在上面的示例中使用 `OneToOneField`,則意味著對於每個 Dreamreal 條目,只有一個 Online 條目是可能的,反之亦然。

最後一個是 `ManyToManyField`,用於表之間的 (n-n) 關係。請注意,這些與基於 SQL 的資料庫相關。

Django - 頁面重定向

在 Web 應用程式中,出於多種原因需要頁面重定向。當發生特定操作時,您可能希望將使用者重定向到另一個頁面,或者基本上是在發生錯誤的情況下。例如,當用戶登入到您的網站時,他通常會重定向到主主頁或他的個人儀表盤。在 Django 中,重定向是使用 'redirect' 方法完成的。

'redirect' 方法的引數:您想要重定向到的 URL(字串)檢視名稱。

到目前為止,`myapp/views` 看起來如下:

def hello(request):
   today = datetime.datetime.now().date()
   daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
   return render(request, "hello.html", {"today" : today, "days_of_week" : daysOfWeek})
	
def viewArticle(request, articleId):
   """ A view that display an article based on his ID"""
   text = "Displaying article Number : %s" %articleId
   return HttpResponse(text)
	
def viewArticles(request, year, month):
   text = "Displaying articles of : %s/%s"%(year, month)
   return HttpResponse(text)

讓我們將 hello 檢視更改為重定向到 djangoproject.com,並將我們的 viewArticle 重定向到我們的內部 '/myapp/articles'。為此,`myapp/view.py` 將更改為:

from django.shortcuts import render, redirect
from django.http import HttpResponse
import datetime

# Create your views here.
def hello(request):
   today = datetime.datetime.now().date()
   daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
   return redirect("https://www.djangoproject.com")
	
def viewArticle(request, articleId):
   """ A view that display an article based on his ID"""
   text = "Displaying article Number : %s" %articleId
   return redirect(viewArticles, year = "2045", month = "02")
	
def viewArticles(request, year, month):
   text = "Displaying articles of : %s/%s"%(year, month)
   return HttpResponse(text)

在上面的例子中,我們首先從 `django.shortcuts` 匯入 `redirect`,對於重定向到 Django 官方網站,我們只需將完整的 URL 作為字串傳遞給 'redirect' 方法,對於第二個例子(viewArticle 檢視),'redirect' 方法將檢視名稱及其引數作為引數。

訪問 /myapp/hello,將顯示以下螢幕:

Django page Redirection Example1

訪問 /myapp/article/42,將顯示以下螢幕:

Django page Redirection Example2

還可以透過新增 `permanent = True` 引數來指定重定向是臨時的還是永久的。使用者不會看到任何區別,但這對於搜尋引擎在對您的網站進行排名時考慮的細節。

還要記住我們在對映 URL 時在 `url.py` 中定義的 'name' 引數:

url(r'^articles/(?P\d{2})/(?P\d{4})/', 'viewArticles', name = 'articles'),

該名稱(此處為 article)可以用作 'redirect' 方法的引數,然後我們的 viewArticle 重定向可以從:

def viewArticle(request, articleId):
   """ A view that display an article based on his ID"""
   text = "Displaying article Number : %s" %articleId
   return redirect(viewArticles, year = "2045", month = "02")

**更改為:**

def viewArticle(request, articleId):
   """ A view that display an article based on his ID"""
   text = "Displaying article Number : %s" %articleId
   return redirect(articles, year = "2045", month = "02")

**注意** - 還有一個函式可以生成 URL;它與 redirect 的使用方法相同;'reverse' 方法(`django.core.urlresolvers.reverse`)。此函式不返回 `HttpResponseRedirect` 物件,而只是一個包含使用任何傳遞的引數編譯的檢視的 URL 的字串。

Django - 傳送郵件

Django 帶有一個易於使用的輕量級引擎來發送電子郵件。與 Python 類似,您只需要匯入 `smtplib`。在 Django 中,您只需要匯入 `django.core.mail`。要開始傳送電子郵件,請編輯您的專案 `settings.py` 檔案並設定以下選項:

  • **`EMAIL_HOST`** - smtp 伺服器。

  • **`EMAIL_HOST_USER`** - smtp 伺服器的登入憑據。

  • **`EMAIL_HOST_PASSWORD`** - smtp 伺服器的密碼憑據。

  • **`EMAIL_PORT`** - smtp 伺服器埠。

  • **`EMAIL_USE_TLS` 或 `_SSL`** - 如果是安全連線,則為 True。

傳送簡單的電子郵件

讓我們建立一個 "sendSimpleEmail" 檢視來發送簡單的電子郵件。

from django.core.mail import send_mail
from django.http import HttpResponse

def sendSimpleEmail(request,emailto):
   res = send_mail("hello paul", "comment tu vas?", "paul@polo.com", [emailto])
   return HttpResponse('%s'%res)

以下是 `send_mail` 引數的詳細資訊:

  • **`subject`** - 電子郵件主題。

  • **`message`** - 電子郵件正文。

  • **`from_email`** - 發件人郵箱。

  • **`recipient_list`** - 收件人郵箱地址列表。

  • **`fail_silently`** - 布林值,如果為 false,則 `send_mail` 將在發生錯誤時引發異常。

  • **`auth_user`** - 如果未在 `settings.py` 中設定,則為使用者登入名。

  • **`auth_password`** - 如果未在 `settings.py` 中設定,則為使用者密碼。

  • **`connection`** - 電子郵件後端。

  • **`html_message`** - (Django 1.7 中的新增功能)如果存在,電子郵件將是 multipart/alternative。

讓我們建立一個 URL 來訪問我們的檢視:

from django.conf.urls import patterns, url

urlpatterns = paterns('myapp.views', url(r'^simpleemail/(?P<emailto>
   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/', 
   'sendSimpleEmail' , name = 'sendSimpleEmail'),)

因此,當訪問 /myapp/simpleemail/polo@gmail.com 時,您將看到以下頁面:

Sending Simple E-mail

使用 `send_mass_mail` 傳送多封郵件

該方法返回成功傳送的訊息數量。這與 `send_mail` 相同,但需要一個額外的引數;`datatuple`,我們的 `sendMassEmail` 檢視將如下所示:

from django.core.mail import send_mass_mail
from django.http import HttpResponse

def sendMassEmail(request,emailto):
   msg1 = ('subject 1', 'message 1', 'polo@polo.com', [emailto1])
   msg2 = ('subject 2', 'message 2', 'polo@polo.com', [emailto2])
   res = send_mass_mail((msg1, msg2), fail_silently = False)
   return HttpResponse('%s'%res)

讓我們建立一個 URL 來訪問我們的檢視:

from django.conf.urls import patterns, url

urlpatterns = paterns('myapp.views', url(r'^massEmail/(?P<emailto1>
   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/(?P<emailto2>
   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})', 'sendMassEmail' , name = 'sendMassEmail'),)

當訪問 /myapp/massemail/polo@gmail.com/sorex@gmail.com/ 時,我們將得到:

Sending Multiple Mails

`send_mass_mail` 引數詳細資訊:

  • **`datatuples`** - 一個元組,其中每個元素都像 (subject, message, from_email, recipient_list)。

  • **`fail_silently`** - 布林值,如果為 false,則 `send_mail` 將在發生錯誤時引發異常。

  • **`auth_user`** - 如果未在 `settings.py` 中設定,則為使用者登入名。

  • **`auth_password`** - 如果未在 `settings.py` 中設定,則為使用者密碼。

  • **`connection`** - 電子郵件後端。

正如你在上圖中看到的,兩封郵件已成功傳送。

**注意** - 在此示例中,我們使用的是 Python smtp 除錯伺服器,您可以使用以下命令啟動:

$python -m smtpd -n -c DebuggingServer localhost:1025

這意味著您傳送的所有電子郵件都將列印在標準輸出上,並且虛擬伺服器正在 localhost:1025 上執行。

使用 `mail_admins` 和 `mail_managers` 方法向管理員和管理人員傳送電子郵件

這些方法將電子郵件傳送給 `settings.py` 檔案的 `ADMINS` 選項中定義的站點管理員,以及 `settings.py` 檔案的 `MANAGERS` 選項中定義的站點管理員。讓我們假設我們的 `ADMINS` 和 `MANAGERS` 選項如下所示:

**`ADMINS`** = (('polo', 'polo@polo.com'),)

**`MANAGERS`** = (('popoli', 'popoli@polo.com'),)

from django.core.mail import mail_admins
from django.http import HttpResponse

def sendAdminsEmail(request):
   res = mail_admins('my subject', 'site is going down.')
   return HttpResponse('%s'%res)

上面的程式碼將向 `ADMINS` 部分中定義的每個管理員傳送一封電子郵件。

from django.core.mail import mail_managers
from django.http import HttpResponse

def sendManagersEmail(request):
   res = mail_managers('my subject 2', 'Change date on the site.')
   return HttpResponse('%s'%res)

上面的程式碼將向 `MANAGERS` 部分中定義的每個管理員傳送一封電子郵件。

引數詳情:

  • **`Subject`** - 電子郵件主題。

  • **`message`** - 電子郵件正文。

  • **`fail_silently`** - 布林值,如果為 false,則 `send_mail` 將在發生錯誤時引發異常。

  • **`connection`** - 電子郵件後端。

  • **`html_message`** - (Django 1.7 中的新增功能)如果存在,電子郵件將是 multipart/alternative。

傳送 HTML 電子郵件

在 Django >= 1.7 中傳送 HTML 訊息非常簡單:

from django.core.mail import send_mail

from django.http import HttpResponse
   res = send_mail("hello paul", "comment tu vas?", "paul@polo.com", 
         ["polo@gmail.com"], html_message=")

這將生成一個 multipart/alternative 電子郵件。

但是對於 Django < 1.7,傳送 HTML 訊息是透過 `django.core.mail.EmailMessage` 類完成的,然後在物件上呼叫 'send':

讓我們建立一個 "sendHTMLEmail" 檢視來發送 HTML 電子郵件。

from django.core.mail import EmailMessage
from django.http import HttpResponse

def sendHTMLEmail(request , emailto):
   html_content = "<strong>Comment tu vas?</strong>"
   email = EmailMessage("my subject", html_content, "paul@polo.com", [emailto])
   email.content_subtype = "html"
   res = email.send()
   return HttpResponse('%s'%res)

`EmailMessage` 類建立的引數詳細資訊:

  • **`Subject`** - 電子郵件主題。

  • **`message`** - HTML 格式的電子郵件正文。

  • **`from_email`** - 發件人郵箱。

  • **`to`** - 收件人郵箱地址列表。

  • **`bcc`** - “Bcc” 收件人郵箱地址列表。

  • **`connection`** - 電子郵件後端。

讓我們建立一個 URL 來訪問我們的檢視:

from django.conf.urls import patterns, url

urlpatterns = paterns('myapp.views', url(r'^htmlemail/(?P<emailto>
   [\w.%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4})/', 
   'sendHTMLEmail' , name = 'sendHTMLEmail'),)

當訪問 /myapp/htmlemail/polo@gmail.com 時,我們將得到:

Sending HTML E-mail

傳送帶有附件的電子郵件

這是透過在 `EmailMessage` 物件上使用 'attach' 方法完成的。

傳送帶有附件的電子郵件的檢視將是:

from django.core.mail import EmailMessage
from django.http import HttpResponse

def sendEmailWithAttach(request, emailto):
   html_content = "Comment tu vas?"
   email = EmailMessage("my subject", html_content, "paul@polo.com", emailto])
   email.content_subtype = "html"
   
   fd = open('manage.py', 'r')
   email.attach('manage.py', fd.read(), 'text/plain')
   
   res = email.send()
   return HttpResponse('%s'%res)

`attach` 引數的詳細資訊:

  • **`filename`** - 要附加的檔名。

  • **`content`** - 要附加的檔案內容。

  • **`mimetype`** - 附件的內容 mime 型別。

Django - 通用檢視

在某些情況下,編寫檢視(正如我們前面看到的)非常繁重。想象一下,您需要一個靜態頁面或一個列表頁面。Django 提供了一種簡單的方法來設定這些簡單的檢視,稱為泛型檢視。

與經典檢視不同,泛型檢視是類而不是函式。Django 在 `django.views.generic` 中提供了一組泛型檢視類,每個泛型檢視都是這些類之一或繼承自這些類之一的類。

有 10 多個泛型類:

>>> import django.views.generic
>>> dir(django.views.generic)

['ArchiveIndexView', 'CreateView', 'DateDetailView', 'DayArchiveView', 
   'DeleteView', 'DetailView', 'FormView', 'GenericViewError', 'ListView', 
   'MonthArchiveView', 'RedirectView', 'TemplateView', 'TodayArchiveView', 
   'UpdateView', 'View', 'WeekArchiveView', 'YearArchiveView', '__builtins__', 
   '__doc__', '__file__', '__name__', '__package__', '__path__', 'base', 'dates', 
   'detail', 'edit', 'list']

您可以將此用於您的泛型檢視。讓我們看一些示例來了解它的工作原理。

靜態頁面

讓我們釋出來自“static.html”模板的靜態頁面。

我們的 `static.html`:

<html>
   <body> 
      This is a static page!!! 
   </body>
</html>

如果我們以前學習過的方法去做,我們將不得不更改 **`myapp/views.py`** 為:

from django.shortcuts import render

def static(request):
   return render(request, 'static.html', {})

和 **`myapp/urls.py`** 為:

from django.conf.urls import patterns, url

urlpatterns = patterns("myapp.views", url(r'^static/', 'static', name = 'static'),)

最佳方法是使用泛型檢視。為此,我們的myapp/views.py將變成:

from django.views.generic import TemplateView

class StaticView(TemplateView):
   template_name = "static.html"

我們的myapp/urls.py將變成:

from myapp.views import StaticView
from django.conf.urls import patterns

urlpatterns = patterns("myapp.views", (r'^static/$', StaticView.as_view()),)

訪問/myapp/static時,您將獲得:

Static Page

為了得到相同的結果,我們也可以執行以下操作:

  • views.py無需更改
  • 將url.py檔案更改為:
from django.views.generic import TemplateView
from django.conf.urls import patterns, url

urlpatterns = patterns("myapp.views",
   url(r'^static/',TemplateView.as_view(template_name = 'static.html')),)

如您所見,在第二種方法中,您只需要更改url.py檔案。

從資料庫列出和顯示資料

我們將列出Dreamreal模型中的所有條目。使用ListView泛型檢視類可以輕鬆實現此操作。編輯url.py檔案並將其更新為:

from django.views.generic import ListView
from django.conf.urls import patterns, url

urlpatterns = patterns(
   "myapp.views", url(r'^dreamreals/', ListView.as_view(model = Dreamreal, 
      template_name = "dreamreal_list.html")),
)

在此需要注意的是,泛型檢視傳遞給模板的變數是object_list。如果您想自己命名它,則需要向as_view方法新增context_object_name引數。然後url.py將變成:

from django.views.generic import ListView
from django.conf.urls import patterns, url

urlpatterns = patterns("myapp.views",
   url(r'^dreamreals/', ListView.as_view(
      template_name = "dreamreal_list.html")),
      model = Dreamreal, context_object_name = ”dreamreals_objects” ,)

關聯的模板將是:

{% extends "main_template.html" %}
{% block content %}
Dreamreals:<p>
{% for dr in object_list %}
{{dr.name}}</p>
{% endfor %}
{% endblock %}

訪問/myapp/dreamreals/將生成以下頁面:

List and Display Data from DB

Django - 表單處理

在Django中建立表單與建立模型非常相似。在這裡,我們只需要繼承自Django類,類屬性將是表單欄位。讓我們在myapp資料夾中新增一個**forms.py**檔案來包含我們的應用程式表單。我們將建立一個登入表單。

myapp/forms.py

#-*- coding: utf-8 -*-
from django import forms

class LoginForm(forms.Form):
   user = forms.CharField(max_length = 100)
   password = forms.CharField(widget = forms.PasswordInput())

如上所示,欄位型別可以接受“widget”引數用於html渲染;在我們的例子中,我們希望密碼被隱藏,而不是顯示。Django中還有許多其他widget:用於日期的**DateInput**,用於複選框的**CheckboxInput**等等。

在檢視中使用表單

有兩種HTTP請求,GET和POST。在Django中,作為引數傳遞給您的檢視的請求物件具有一個名為“method”的屬性,其中設定了請求的型別,並且可以透過request.POST字典訪問透過POST傳遞的所有資料。

讓我們在我們的myapp/views.py中建立一個登入檢視:

#-*- coding: utf-8 -*-
from myapp.forms import LoginForm

def login(request):
   username = "not logged in"
   
   if request.method == "POST":
      #Get the posted form
      MyLoginForm = LoginForm(request.POST)
      
      if MyLoginForm.is_valid():
         username = MyLoginForm.cleaned_data['username']
   else:
      MyLoginForm = Loginform()
		
   return render(request, 'loggedin.html', {"username" : username})

該檢視將顯示透過**loggedin.html**提交的登入表單的結果。為了測試它,我們首先需要登入表單模板。讓我們稱之為login.html。

<html>
   <body>
      
      <form name = "form" action = "{% url "myapp.views.login" %}" 
         method = "POST" >{% csrf_token %}
         
         <div style = "max-width:470px;">
            <center> 
               <input type = "text" style = "margin-left:20%;" 
                  placeholder = "Identifiant" name = "username" />
            </center>
         </div>
			
         <br>
         
         <div style = "max-width:470px;">
            <center>
               <input type = "password" style = "margin-left:20%;" 
                  placeholder = "password" name = "password" />
            </center>
         </div>
			
         <br>
         
         <div style = "max-width:470px;">
            <center> 
            
               <button style = "border:0px; background-color:#4285F4; margin-top:8%;
                  height:35px; width:80%;margin-left:19%;" type = "submit" 
                  value = "Login" >
                  <strong>Login</strong>
               </button>
               
            </center>
         </div>
         
      </form>
      
   </body>
</html>

該模板將顯示一個登入表單並將結果釋出到我們上面的登入檢視。您可能已經注意到模板中的標籤,它只是為了防止對您網站的跨站點請求偽造 (CSRF) 攻擊。

{% csrf_token %}

擁有登入模板後,我們需要在表單處理後呈現的loggedin.html模板。

<html>
   
   <body>
      You are : <strong>{{username}}</strong>
   </body>
   
</html>

現在,我們只需要我們的URL對即可開始:myapp/urls.py

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns('myapp.views',
   url(r'^connection/',TemplateView.as_view(template_name = 'login.html')),
   url(r'^login/', 'login', name = 'login'))

訪問“/myapp/connection”時,我們將獲得呈現的以下login.html模板:

Login HTML Template

在表單提交後,表單有效。在我們的例子中,確保填寫這兩個欄位,您將得到:

Form Validation

如果您的使用者名稱是polo,並且您忘記了密碼。您將收到以下訊息:

Form Invalid Message

使用我們自己的表單驗證

在上面的例子中,驗證表單時:

MyLoginForm.is_valid()

我們只使用了Django自身的表單驗證引擎,在我們的例子中只是確保欄位是必需的。現在讓我們確保嘗試登入的使用者存在於我們的資料庫中作為Dreamreal條目。為此,將myapp/forms.py更改為:

#-*- coding: utf-8 -*-
from django import forms
from myapp.models import Dreamreal

class LoginForm(forms.Form):
   user = forms.CharField(max_length = 100)
   password = forms.CharField(widget = forms.PasswordInput())

   def clean_message(self):
      username = self.cleaned_data.get("username")
      dbuser = Dreamreal.objects.filter(name = username)
      
      if not dbuser:
         raise forms.ValidationError("User does not exist in our db!")
      return username

現在,在呼叫“is_valid”方法後,只有當用戶在我們的資料庫中時,我們才能獲得正確的輸出。如果您想檢查表單的欄位,只需在表單類中新增一個以“clean_”開頭的方法,然後是您的欄位名稱。引發forms.ValidationError非常重要。

Django - 檔案上傳

對於 Web 應用來說,能夠上傳檔案(個人資料圖片、歌曲、pdf、文件……)通常很有用。本章將討論如何上傳檔案。

上傳影像

在開始使用影像之前,請確保已安裝 Python 影像庫 (PIL)。現在,為了說明如何上傳影像,讓我們在我們的myapp/forms.py中建立一個個人資料表單:

#-*- coding: utf-8 -*-
from django import forms

class ProfileForm(forms.Form):
   name = forms.CharField(max_length = 100)
   picture = forms.ImageFields()

如您所見,這裡的主要區別只是**forms.ImageField**。ImageField 將確保上傳的檔案是影像。如果不是,則表單驗證將失敗。

現在讓我們建立一個“Profile”模型來儲存我們上傳的個人資料。這在myapp/models.py中完成:

from django.db import models

class Profile(models.Model):
   name = models.CharField(max_length = 50)
   picture = models.ImageField(upload_to = 'pictures')

   class Meta:
      db_table = "profile"

如您所見,對於模型,ImageField 需要一個強制性引數:**upload_to**。這表示將在硬碟驅動器上儲存影像的位置。請注意,該引數將新增到您的settings.py檔案中定義的MEDIA_ROOT選項中。

現在我們有了表單和模型,讓我們在myapp/views.py中建立檢視:

#-*- coding: utf-8 -*-
from myapp.forms import ProfileForm
from myapp.models import Profile

def SaveProfile(request):
   saved = False
   
   if request.method == "POST":
      #Get the posted form
      MyProfileForm = ProfileForm(request.POST, request.FILES)
      
      if MyProfileForm.is_valid():
         profile = Profile()
         profile.name = MyProfileForm.cleaned_data["name"]
         profile.picture = MyProfileForm.cleaned_data["picture"]
         profile.save()
         saved = True
   else:
      MyProfileForm = Profileform()
		
   return render(request, 'saved.html', locals())

需要注意的部分是,建立ProfileForm時有一個變化,我們添加了第二個引數:**request.FILES**。如果沒有傳遞,表單驗證將失敗,並顯示圖片為空的訊息。

現在,我們只需要**saved.html**模板和**profile.html**模板,用於表單和重定向頁面:

**myapp/templates/saved.html**:

<html>
   <body>
   
      {% if saved %}
         <strong>Your profile was saved.</strong>
      {% endif %}
      
      {% if not saved %}
         <strong>Your profile was not saved.</strong>
      {% endif %}
      
   </body>
</html>

**myapp/templates/profile.html**:

<html>
   <body>
   
      <form name = "form" enctype = "multipart/form-data" 
         action = "{% url "myapp.views.SaveProfile" %}" method = "POST" >{% csrf_token %}
         
         <div style = "max-width:470px;">
            <center>  
               <input type = "text" style = "margin-left:20%;" 
               placeholder = "Name" name = "name" />
            </center>
         </div>
			
         <br>
         
         <div style = "max-width:470px;">
            <center> 
               <input type = "file" style = "margin-left:20%;" 
                  placeholder = "Picture" name = "picture" />
            </center>
         </div>
			
         <br>
         
         <div style = "max-width:470px;">
            <center> 
            
               <button style = "border:0px;background-color:#4285F4; margin-top:8%; 
                  height:35px; width:80%; margin-left:19%;" type = "submit" value = "Login" >
                  <strong>Login</strong>
               </button>
               
            </center>
         </div>
         
      </form>
      
   </body>
</html>

接下來,我們需要我們的URL對才能開始:myapp/urls.py

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns(
   'myapp.views', url(r'^profile/',TemplateView.as_view(
      template_name = 'profile.html')), url(r'^saved/', 'SaveProfile', name = 'saved')
)

訪問“/myapp/profile”時,我們將獲得呈現的以下profile.html模板:

Uploading Image

在表單提交後,將呈現saved模板:

Form Post Template

我們有一個影像示例,但是如果您想上傳其他型別的檔案,而不僅僅是影像,只需將模型和表單中的**ImageField**替換為**FileField**。

Django - Apache 配置

到目前為止,在我們的示例中,我們使用了Django開發Web伺服器。但是這個伺服器只是用於測試,不適合生產環境。投入生產後,您需要一個真正的伺服器,例如Apache、Nginx等。本章將討論Apache。

透過Apache提供Django應用程式是透過使用mod_wsgi完成的。因此,首先要確保已安裝Apache和mod_wsgi。請記住,當我們建立專案並檢視專案結構時,它看起來像:

myproject/
   manage.py
   myproject/
      __init__.py
      settings.py
      urls.py
      wsgi.py

wsgi.py檔案負責處理Django和Apache之間的連結。

假設我們要與Apache共享我們的專案(myproject)。我們只需要設定Apache來訪問我們的資料夾。假設我們將myproject資料夾放在預設的“/var/www/html”中。在這個階段,訪問專案將透過127.0.0.1/myproject完成。這將導致Apache只列出資料夾,如下面的快照所示。

Django Apache Setup

如您所見,Apache沒有處理Django內容。為了解決這個問題,我們需要在httpd.conf中配置Apache。因此,開啟httpd.conf並新增以下行:

WSGIScriptAlias / /var/www/html/myproject/myproject/wsgi.py
WSGIPythonPath /var/www/html/myproject/

<Directory /var/www/html/myproject/>
   <Files wsgi.py>
      Order deny,allow
      Allow from all
   </Files>
</Directory>

如果您能以127.0.0.1/myapp/connection訪問登入頁面,您將看到以下頁面:

Login Page

Django - Cookie 處理

有時,您可能希望根據 Web 應用程式的要求,按每個站點訪問者的基礎儲存一些資料。始終記住,cookie 儲存在客戶端,並且取決於客戶端瀏覽器的安全級別,設定 cookie 有時有效,有時可能無效。

為了說明在Django中處理cookie,讓我們建立一個使用我們之前建立的登入系統的系統。該系統將讓您登入X分鐘的時間,超過該時間,您將退出應用程式。

為此,您需要設定兩個cookie,last_connection和username。

首先,讓我們更改登入檢視以儲存我們的使用者名稱和last_connection cookie:

from django.template import RequestContext

def login(request):
   username = "not logged in"
   
   if request.method == "POST":
      #Get the posted form
      MyLoginForm = LoginForm(request.POST)
   
   if MyLoginForm.is_valid():
      username = MyLoginForm.cleaned_data['username']
   else:
      MyLoginForm = LoginForm()
   
   response = render_to_response(request, 'loggedin.html', {"username" : username}, 
      context_instance = RequestContext(request))
   
   response.set_cookie('last_connection', datetime.datetime.now())
   response.set_cookie('username', datetime.datetime.now())
	
   return response

如上圖所示,設定cookie是透過對響應而不是請求呼叫的**set_cookie**方法完成的,並且請注意所有cookie值都作為字串返回。

現在讓我們為登入表單建立一個formView,如果設定了cookie並且cookie不超過10秒,我們將不顯示錶單:

def formView(request):
   if 'username' in request.COOKIES and 'last_connection' in request.COOKIES:
      username = request.COOKIES['username']
      
      last_connection = request.COOKIES['last_connection']
      last_connection_time = datetime.datetime.strptime(last_connection[:-7], 
         "%Y-%m-%d %H:%M:%S")
      
      if (datetime.datetime.now() - last_connection_time).seconds < 10:
         return render(request, 'loggedin.html', {"username" : username})
      else:
         return render(request, 'login.html', {})
			
   else:
      return render(request, 'login.html', {})

如上所示的formView中,訪問您設定的cookie是透過請求的COOKIES屬性(字典)完成的。

現在讓我們更改url.py檔案以更改URL,使其與我們的新檢視配對:

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns('myapp.views',
   url(r'^connection/','formView', name = 'loginform'),
   url(r'^login/', 'login', name = 'login'))

訪問/myapp/connection時,您將看到以下頁面:

Django Cookies Handling

提交後,您將被重定向到以下螢幕:

Cookies Handling Redirected Page

現在,如果您嘗試在10秒範圍內再次訪問/myapp/connection,您將直接被重定向到第二個螢幕。如果您在此範圍之外再次訪問/myapp/connection,您將獲得登入表單(螢幕1)。

Django - Session

如前所述,我們可以使用客戶端cookie來儲存許多對Web應用程式有用的資料。我們之前已經看到,我們可以使用客戶端cookie來儲存對我們的Web應用程式有用的各種資料。這會導致許多安全漏洞,具體取決於您要儲存的資料的重要性。

出於安全原因,Django有一個用於處理cookie的會話框架。會話用於抽象接收和傳送cookie,資料儲存在伺服器端(例如在資料庫中),客戶端cookie只有一個會話ID用於標識。會話也有助於避免使用者瀏覽器設定為“不接受”cookie的情況。

設定會話

在Django中,啟用會話是在您的專案**settings.py**中完成的,方法是向**MIDDLEWARE_CLASSES**和**INSTALLED_APPS**選項新增一些行。這應該在建立專案時完成,但瞭解這一點總是好的,因此**MIDDLEWARE_CLASSES**應該具有:

'django.contrib.sessions.middleware.SessionMiddleware'

而**INSTALLED_APPS**應該具有:

'django.contrib.sessions'

預設情況下,Django將會話資訊儲存在資料庫中(django_session表或集合),但您可以配置引擎以使用其他方式儲存資訊,例如:在**檔案**中或在**快取**中。

啟用會話後,每個請求(Django中任何檢視的第一個引數)都具有一個session(字典)屬性。

讓我們建立一個簡單的示例,看看如何建立和儲存會話。我們之前構建了一個簡單的登入系統(請參閱Django表單處理章節和Django Cookie處理章節)。讓我們將使用者名稱儲存在cookie中,因此,如果沒有登出,當訪問我們的登入頁面時,您將看不到登入表單。基本上,讓我們使我們在Django Cookie處理中使用的登入系統更安全,方法是將cookie儲存在伺服器端。

為此,首先讓我們更改登入檢視以將使用者名稱cookie儲存在伺服器端:

def login(request):
   username = 'not logged in'
   
   if request.method == 'POST':
      MyLoginForm = LoginForm(request.POST)
      
      if MyLoginForm.is_valid():
         username = MyLoginForm.cleaned_data['username']
         request.session['username'] = username
      else:
         MyLoginForm = LoginForm()
			
   return render(request, 'loggedin.html', {"username" : username}

然後讓我們為登入表單建立formView檢視,如果設定了cookie,我們將不顯示錶單:

def formView(request):
   if request.session.has_key('username'):
      username = request.session['username']
      return render(request, 'loggedin.html', {"username" : username})
   else:
      return render(request, 'login.html', {})

現在讓我們更改url.py檔案以更改URL,使其與我們的新檢視配對:

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns('myapp.views',
   url(r'^connection/','formView', name = 'loginform'),
   url(r'^login/', 'login', name = 'login'))

訪問/myapp/connection時,您將看到以下頁面:

Setting Up Sessions

您將被重定向到以下頁面:

Sessions Redirected Page

現在,如果您嘗試再次訪問/myapp/connection,您將直接被重定向到第二個螢幕。

讓我們建立一個簡單的登出檢視來刪除我們的cookie。

def logout(request):
   try:
      del request.session['username']
   except:
      pass
   return HttpResponse("<strong>You are logged out.</strong>")

並將其與myapp/url.py中的登出URL配對

url(r'^logout/', 'logout', name = 'logout'),

現在,如果您訪問/myapp/logout,您將看到以下頁面:

Logged Out Page

如果您再次訪問/myapp/connection,您將獲得登入表單(螢幕1)。

使用會話可以執行的更多可能的動作

我們已經學習瞭如何儲存和訪問會話,但瞭解請求的會話屬性還有一些其他有用的操作也很重要:

  • set_expiry (value) − 設定會話的過期時間。

  • get_expiry_age() − 返回此會話過期前的秒數。

  • get_expiry_date() − 返回此會話將過期的日期。

  • clear_expired() − 從會話儲存中刪除過期的會話。

  • get_expire_at_browser_close() − 返回 True 或 False,取決於使用者關閉瀏覽器時使用者會話 cookie 是否已過期。

Django - 快取

快取是指儲存昂貴計算的結果,以便在下次需要時無需再次執行。下面是一個虛擬碼,解釋了快取的工作原理:

given a URL, try finding that page in the cache

if the page is in the cache:
   return the cached page
else:
   generate the page
   save the generated page in the cache (for next time)
   return the generated page

Django 自帶自己的快取系統,允許您儲存動態頁面,避免在需要時再次計算它們。Django 快取框架的優點在於您可以快取:

  • 特定檢視的輸出。
  • 模板的一部分。
  • 您的整個站點。

要在 Django 中使用快取,首先需要設定快取的儲存位置。快取框架提供了不同的可能性——快取可以儲存在資料庫中、檔案系統中或直接儲存在記憶體中。設定是在專案的 settings.py 檔案中完成的。

在資料庫中設定快取

只需在專案 settings.py 檔案中新增以下內容:

CACHES = {
   'default': {
      'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
      'LOCATION': 'my_table_name',
   }
}

為了使此設定生效並完成設定,我們需要建立快取表“my_table_name”。為此,您需要執行以下操作:

python manage.py createcachetable

在檔案系統中設定快取

只需在專案 settings.py 檔案中新增以下內容:

CACHES = {
   'default': {
      'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
      'LOCATION': '/var/tmp/django_cache',
   }
}

在記憶體中設定快取

這是最有效的快取方式,您可以根據為記憶體快取選擇的 Python 繫結庫使用以下選項之一:

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',
   }
}

快取整個站點

在 Django 中使用快取最簡單的方法是快取整個站點。這是透過編輯專案 settings.py 中的 MIDDLEWARE_CLASSES 選項來完成的。需要向該選項新增以下內容:

MIDDLEWARE_CLASSES += (
   'django.middleware.cache.UpdateCacheMiddleware',
   'django.middleware.common.CommonMiddleware',
   'django.middleware.cache.FetchFromCacheMiddleware',
)

請注意,這裡的順序很重要,Update 應該在 Fetch 中介軟體之前。

然後在同一個檔案中,您需要設定:

CACHE_MIDDLEWARE_ALIAS – The cache alias to use for storage.
CACHE_MIDDLEWARE_SECONDS – The number of seconds each page should be cached.

快取檢視

如果您不想快取整個站點,您可以快取特定的檢視。這是透過使用 Django 自帶的 cache_page 裝飾器來完成的。假設我們要快取 viewArticles 檢視的結果:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)

def viewArticles(request, year, month):
   text = "Displaying articles of : %s/%s"%(year, month)
   return HttpResponse(text)

如您所見,cache_page 將檢視結果快取的秒數作為引數。在上面的示例中,結果將快取 15 分鐘。

注意 − 正如我們之前看到的,上面的檢視對映到:

urlpatterns = patterns('myapp.views',
   url(r'^articles/(?P<month>\d{2})/(?P<year>\d{4})/', 'viewArticles', name = 'articles'),)

由於 URL 正在獲取引數,因此每個不同的呼叫都將單獨快取。例如,對 /myapp/articles/02/2007 的請求將與對 /myapp/articles/03/2008 的請求分別快取。

也可以直接在 url.py 檔案中快取檢視。然後,以下內容與上述內容具有相同的結果。只需編輯您的 myapp/url.py 檔案並更改相關的對映 URL(如上)為:

urlpatterns = patterns('myapp.views',
   url(r'^articles/(?P<month>\d{2})/(?P<year>\d{4})/', 
   cache_page(60 * 15)('viewArticles'), name = 'articles'),)

當然,myapp/views.py 中不再需要它了。

快取模板片段

您還可以快取模板的一部分,這是透過使用 cache 標籤來完成的。讓我們以我們的 hello.html 模板為例:

{% extends "main_template.html" %}
{% block title %}My Hello Page{% endblock %}
{% block content %}

Hello World!!!<p>Today is {{today}}</p>
We are
{% if today.day == 1 %}

the first day of month.
{% elif today.day == 30 %}

the last day of month.
{% else %}

I don't know.
{%endif%}

<p>
   {% for day in days_of_week %}
   {{day}}
</p>

{% endfor %}
{% endblock %}

為了快取內容塊,我們的模板將變為:

{% load cache %}
{% extends "main_template.html" %}
{% block title %}My Hello Page{% endblock %}
{% cache 500 content %}
{% block content %}

Hello World!!!<p>Today is {{today}}</p>
We are
{% if today.day == 1 %}

the first day of month.
{% elif today.day == 30 %}

the last day of month.
{% else %}

I don't know.
{%endif%}

<p>
   {% for day in days_of_week %}
   {{day}}
</p>

{% endfor %}
{% endblock %}
{% endcache %}

如您在上面看到的,cache 標籤將接受兩個引數:要快取塊的時間(以秒為單位)和要賦予快取片段的名稱。

Django - 評論

在開始之前,請注意,Django 評論框架自 1.5 版本起已棄用。現在您可以使用外部功能來實現此目的,但如果您仍然想要使用它,它仍然包含在 1.6 和 1.7 版本中。從 1.8 版本開始,它不存在,但您仍然可以在不同的 GitHub 帳戶上獲取程式碼。

評論框架使您可以輕鬆地將評論附加到應用程式中的任何模型。

要開始使用 Django 評論框架:

編輯專案 settings.py 檔案,並將 'django.contrib.sites''django.contrib.comments' 新增到 INSTALLED_APPS 選項:

INSTALLED_APPS += ('django.contrib.sites', 'django.contrib.comments',)

獲取站點 ID:

>>> from django.contrib.sites.models import Site
>>> Site().save()
>>> Site.objects.all()[0].id
u'56194498e13823167dd43c64'

在 settings.py 檔案中設定您獲得的 ID:

SITE_ID = u'56194498e13823167dd43c64'

同步資料庫,以建立所有評論表或集合:

python manage.py syncdb

將評論應用程式的 URL 新增到專案的 urls.py:

from django.conf.urls import include
url(r'^comments/', include('django.contrib.comments.urls')),

現在我們已經安裝了框架,讓我們更改 hello 模板以跟蹤我們 Dreamreal 模型上的評論。我們將列出並儲存特定 Dreamreal 條目的評論,其名稱將作為引數傳遞給 /myapp/hello URL。

Dreamreal 模型

class Dreamreal(models.Model):

   website = models.CharField(max_length = 50)
   mail = models.CharField(max_length = 50)
   name = models.CharField(max_length = 50)
   phonenumber = models.IntegerField()

   class Meta:
      db_table = "dreamreal"

hello 檢視

def hello(request, Name):
   today = datetime.datetime.now().date()
   daysOfWeek = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
   dreamreal = Dreamreal.objects.get(name = Name)
   return render(request, 'hello.html', locals())

hello.html 模板

{% extends "main_template.html" %}
{% load comments %}
{% block title %}My Hello Page{% endblock %}
{% block content %}

<p>
   Our Dreamreal Entry:
   <p><strong>Name :</strong> {{dreamreal.name}}</p>
   <p><strong>Website :</strong> {{dreamreal.website}}</p>
   <p><strong>Phone :</strong> {{dreamreal.phonenumber}}</p>
   <p><strong>Number of comments :<strong> 
   {% get_comment_count for dreamreal as comment_count %} {{ comment_count }}</p>
   <p>List of comments :</p>
   {% render_comment_list for dreamreal %}
</p>

{% render_comment_form for dreamreal %}
{% endblock %}

最後是 hello 檢視的對映 URL:

url(r'^hello/(?P<Name>\w+)/', 'hello', name = 'hello'),

現在,

  • 在我們的模板 (hello.html) 中,使用 {% load comments %} 載入評論框架。

  • 我們獲取檢視傳遞的 Dreamreal 物件的評論數量:{% get_comment_count for dreamreal as comment_count %}

  • 我們獲取物件的評論列表:{% render_comment_list for dreamreal %}

  • 我們顯示預設的評論表單:{% render_comment_form for dreamreal %}

訪問 /myapp/hello/steve 時,您將獲得名稱為 Steve 的 Dreamreal 條目的評論資訊。訪問該 URL 將獲得:

Django Comments Example

釋出評論後,您將被重定向到以下頁面:

Comments Redirected Page

如果您再次訪問 /myapp/hello/steve,您將看到以下頁面:

Number of Comments

如您所見,評論數量現在為 1,並且您在評論列表行下有評論。

Django - RSS

Django 帶有一個聯合供稿生成框架。使用它,您可以透過子類化 django.contrib.syndication.views.Feed 類 來建立 RSS 或 Atom 供稿。

讓我們為應用程式上最新的評論建立一個供稿(另請參見 Django - 評論框架章節)。為此,讓我們建立一個 myapp/feeds.py 並定義我們的供稿(您可以將供稿類放在程式碼結構中的任何位置)。

from django.contrib.syndication.views import Feed
from django.contrib.comments import Comment
from django.core.urlresolvers import reverse

class DreamrealCommentsFeed(Feed):
   title = "Dreamreal's comments"
   link = "/drcomments/"
   description = "Updates on new comments on Dreamreal entry."

   def items(self):
      return Comment.objects.all().order_by("-submit_date")[:5]
		
   def item_title(self, item):
      return item.user_name
		
   def item_description(self, item):
      return item.comment
		
   def item_link(self, item):
      return reverse('comment', kwargs = {'object_pk':item.pk})
  • 在我們的供稿類中,titlelinkdescription 屬性對應於標準 RSS <title><link><description> 元素。

  • items 方法返回應作為專案元素新增到供稿中的元素。在本例中,是最近五條評論。

  • item_title 方法將獲取作為供稿專案標題的內容。在本例中,標題將是使用者名稱。

  • item_description 方法將獲取作為供稿專案描述的內容。在本例中,是評論本身。

  • item_link 方法將構建指向完整專案的連結。在本例中,它將引導您到評論。

現在我們有了供稿,讓我們在 views.py 中新增一個評論檢視來顯示我們的評論:

from django.contrib.comments import Comment

def comment(request, object_pk):
   mycomment = Comment.objects.get(object_pk = object_pk)
   text = '<strong>User :</strong> %s <p>'%mycomment.user_name</p>
   text += '<strong>Comment :</strong> %s <p>'%mycomment.comment</p>
   return HttpResponse(text)

我們還需要在 myapp urls.py 中新增一些 URL 用於對映:

from myapp.feeds import DreamrealCommentsFeed
from django.conf.urls import patterns, url

urlpatterns += patterns('',
   url(r'^latest/comments/', DreamrealCommentsFeed()),
   url(r'^comment/(?P\w+)/', 'comment', name = 'comment'),
)

訪問 /myapp/latest/comments/ 時,您將獲得我們的供稿:

Django RSS Example

然後單擊其中一個使用者名稱將轉到:/myapp/comment/comment_id(如我們之前的評論檢視中定義),您將獲得:

Django RSS Redirected Page

因此,定義 RSS 供稿只是子類化 Feed 類並確保定義了 URL(一個用於訪問供稿,一個用於訪問供稿元素)的問題。就像評論一樣,這可以附加到應用程式中的任何模型。

Django - Ajax

Ajax 本質上是整合在一起以減少頁面載入次數的技術組合。我們通常使用 Ajax 來簡化終端使用者體驗。在 Django 中使用 Ajax 可以透過直接使用 Ajax 庫(如 JQuery 或其他庫)來完成。假設您想使用 JQuery,那麼您需要下載並透過 Apache 或其他伺服器在您的伺服器上提供該庫。然後像開發任何基於 Ajax 的應用程式一樣在您的模板中使用它。

在 Django 中使用 Ajax 的另一種方法是使用 Django Ajax 框架。最常用的框架是 django-dajax,它是一個強大的工具,可以使用 Python 和幾乎沒有 JavaScript 原始碼輕鬆快速地在 Web 應用程式中開發非同步表示邏輯。它支援四個最流行的 Ajax 框架:Prototype、jQuery、Dojo 和 MooTools。

使用 Django-dajax

首先需要安裝 django-dajax。這可以使用 easy_install 或 pip 來完成:

$ pip install django_dajax
$ easy_install django_dajax

這將自動安裝 django-dajaxice(django-dajax 需要)。然後我們需要配置 dajax 和 dajaxice。

在專案 settings.py 中的 INSTALLED_APPS 選項中新增 dajax 和 dajaxice:

INSTALLED_APPS += (
   'dajaxice',
   'dajax'
)

確保在同一個 settings.py 檔案中,您具有以下內容:

TEMPLATE_LOADERS = (
   'django.template.loaders.filesystem.Loader',
   'django.template.loaders.app_directories.Loader',
   'django.template.loaders.eggs.Loader',
)

TEMPLATE_CONTEXT_PROCESSORS = (
   'django.contrib.auth.context_processors.auth',
   'django.core.context_processors.debug',
   'django.core.context_processors.i18n',
   'django.core.context_processors.media',
   'django.core.context_processors.static',
   'django.core.context_processors.request',
   'django.contrib.messages.context_processors.messages'
)

STATICFILES_FINDERS = (
   'django.contrib.staticfiles.finders.FileSystemFinder',
   'django.contrib.staticfiles.finders.AppDirectoriesFinder',
   'dajaxice.finders.DajaxiceFinder',
)

DAJAXICE_MEDIA_PREFIX = 'dajaxice'

現在轉到 myapp/url.py 檔案,確保您具有以下內容以設定 dajax URL 並載入 dajax statics js 檔案:

from dajaxice.core import dajaxice_autodiscover, dajaxice_config
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings

Then dajax urls:

urlpatterns += patterns('',
   url(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')),)
	
urlpatterns += staticfiles_urlpatterns()

讓我們建立一個基於我們的 Dreamreal 模型的簡單表單來使用 Ajax 儲存它(意味著無需重新整理)。

首先,我們需要在 myapp/form.py 中的 Dreamreal 表單。

class DreamrealForm(forms.Form):
   website = forms.CharField(max_length = 100)
   name = forms.CharField(max_length = 100)
   phonenumber = forms.CharField(max_length = 50)
   email = forms.CharField(max_length = 100)

然後我們需要在我們的應用程式中建立一個 ajax.py 檔案:myapp/ajax.py。這就是我們的邏輯所在,這就是我們放置儲存表單然後返回彈出視窗的函式的地方:

from dajaxice.utils import deserialize_form
from myapp.form import DreamrealForm
from dajax.core import Dajax
from myapp.models import Dreamreal

@dajaxice_register
def send_form(request, form):
   dajax = Dajax()
   form = DreamrealForm(deserialize_form(form))
   
   if form.is_valid():
      dajax.remove_css_class('#my_form input', 'error')
      dr = Dreamreal()
      dr.website = form.cleaned_data.get('website')
      dr.name = form.cleaned_data.get('name')
      dr.phonenumber = form.cleaned_data.get('phonenumber')
      dr.save()
      
      dajax.alert("Dreamreal Entry %s was successfully saved." % 
         form.cleaned_data.get('name'))
   else:
      dajax.remove_css_class('#my_form input', 'error')
      for error in form.errors:
         dajax.add_css_class('#id_%s' % error, 'error')
			
   return dajax.json()

現在讓我們建立 dreamreal.html 模板,其中包含我們的表單:

<html>
   <head></head>
   <body>
   
      <form action = "" method = "post" id = "my_form" accept-charset = "utf-8">
         {{ form.as_p }}
         <p><input type = "button" value = "Send" onclick = "send_form();"></p>
      </form>
      
   </body>
</html>

在 myapp/views.py 中新增與模板一起使用的檢視:

def dreamreal(request):
   form = DreamrealForm()
   return render(request, 'dreamreal.html', locals())

在 myapp/urls.py 中新增相應的 URL:

url(r'^dreamreal/', 'dreamreal', name = 'dreamreal'),

現在讓我們在模板中新增必要的程式碼以使 Ajax 工作:

在檔案頂部新增:

{% load static %}
{% load dajaxice_templatetags %}

並在 dreamreal.html 模板的 <head> 部分新增:

在此示例中,我們使用的是 JQuery 庫,因此新增:

<script src = "{% static '/static/jquery-1.11.3.min.js' %}" 
   type = "text/javascript" charset = "utf-8"></script>
<script src = "{% static '/static/dajax/jquery.dajax.core.js' %}"></script>

單擊時將呼叫的 Ajax 函式:

<script>

   function send_form(){
      Dajaxice.myapp.send_form(Dajax.process,{'form':$('#my_form').serialize(true)});
   }
</script>

請注意,您需要在靜態檔案目錄中使用“jquery-1.11.3.min.js”,以及 jquery.dajax.core.js。要確保所有 dajax 靜態檔案都在您的靜態目錄下提供服務,請執行:

$python manage.py collectstatic

注意 − 有時 jquery.dajax.core.js 可能丟失,如果發生這種情況,只需下載原始碼並獲取該檔案並將其放入您的靜態資料夾中。

訪問 /myapp/dreamreal/ 時,您將看到以下螢幕:

Using Django-dajax

提交後,您將看到以下螢幕:

Using Django-dajax Response
廣告