多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

中國最全I(xiàn)T社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2

django教程

Django 集成的子框架

閱讀 (2413)

Python有眾多優(yōu)點(diǎn),其中之一就是“開機(jī)即用”原則: 安裝Python的同時(shí)會安裝好大量的標(biāo)準(zhǔn)軟件包,這樣 你可以立即使用而不用自己去下載。 Django也遵循這個原則,它同樣包含了自己的標(biāo)準(zhǔn)庫。 這一章就來講 這些集成的子框架。

Django標(biāo)準(zhǔn)庫

Django的標(biāo)準(zhǔn)庫存放在 django.contrib 包中。每個子包都是一個獨(dú)立的附加功能包。 這些子包一般是互相獨(dú)立的,不過有些django.contrib子包需要依賴其他子包。

在 django.contrib 中對函數(shù)的類型并沒有強(qiáng)制要求 。其中一些包中帶有模型(因此需要你在數(shù)據(jù)庫中安裝對應(yīng)的數(shù)據(jù)表),但其它一些由獨(dú)立的中間件及模板標(biāo)簽組成。

django.contrib 開發(fā)包共有的特性是: 就算你將整個django.contrib開發(fā)包刪除,你依然可以使用 Django 的基礎(chǔ)功能而不會遇到任何問題。 當(dāng) Django 開發(fā)者向框架增加新功能的時(shí),他們會嚴(yán)格根據(jù)這一原則來決定是否把新功能放入django.contrib中。

django.contrib 由以下開發(fā)包組成:

  • admin : 自動化的站點(diǎn)管理工具。 請查看第6章。

  • admindocs:為Django admin站點(diǎn)提供自動文檔。 本書沒有介紹這方面的知識;詳情請參閱Django官方文檔。

  • auth : Django的用戶驗(yàn)證框架。 參見第十四章。

  • comments : 一個評論應(yīng)用,目前,這個應(yīng)用正在緊張的開發(fā)中,因此在本書出版的時(shí)候還不能給出一個完整的說明,關(guān)于這個應(yīng)用的更多信息請參見Django的官方網(wǎng)站. 本書沒有介紹這方面的知識;詳情請參閱Django官方文檔。

  • contenttypes : 這是一個用于引入文檔類型的框架,每個安裝的Django模塊作為一種獨(dú)立的文檔類型。 這個框架主要在Django內(nèi)部被其他應(yīng)用使用,它主要面向Django的高級開發(fā)者。 可以通過閱讀源碼來了解關(guān)于這個框架的更多信息,源碼的位置在 django/contrib/contenttypes/。

  • csrf : 這個模塊用來防御跨站請求偽造(CSRF)。參 見后面標(biāo)題為”CSRF 防御”的小節(jié)。

  • databrowse:幫助你瀏覽數(shù)據(jù)的Django應(yīng)用。 本書沒有介紹這方面的知識;詳情請參閱Django官方文檔。

  • flatpages : 一個在數(shù)據(jù)庫中管理單一HTML內(nèi)容的模塊。 參見后面標(biāo)題為“Flatpages”的小節(jié)。

  • formtools:一些列處理表單通用模式的高級庫。 本書沒有介紹這方面的知識;詳情請參閱Django官方文檔。

  • gis:為Django提供GIS(Geographic Information Systems)支持的擴(kuò)展。 舉個例子,它允許你的Django模型保存地理學(xué)數(shù)據(jù)并執(zhí)行地理學(xué)查詢。 這個庫比較復(fù)雜,本書不詳細(xì)介紹。 請參看http://geodjango.org/上的文檔。

  • humanize : 一系列 Django 模塊過濾器,用于增加數(shù)據(jù)的人性化。 參閱稍后的章節(jié)《人性化數(shù)據(jù)》。

  • localflavor:針對不同國家和文化的混雜代碼段。 例如,它包含了驗(yàn)證美國的郵編 以及愛爾蘭的身份證號的方法。

  • markup : 一系列的 Django 模板過濾器,用于實(shí)現(xiàn)一些常用標(biāo)記語言。 參閱后續(xù)章節(jié)《標(biāo)記過濾器》。

  • redirects : 用來管理重定向的框架。 參看后面的“重定向”小節(jié)。

  • sessions : Django 的會話框架。 參見14章。

  • sitemaps : 用來生成網(wǎng)站地圖的 XML 文件的框架。 參見13章。

  • sites : 一個讓你可以在同一個數(shù)據(jù)庫與 Django 安裝中管理多個網(wǎng)站的框架。 參見下一節(jié):

  • syndication : 一個用 RSS 和 Atom 來生成聚合訂閱源的的框架。 參見13章。

  • webdesign:對設(shè)計(jì)者非常有用的Django擴(kuò)展。 到編寫此文時(shí),它只包含一個模板標(biāo)簽{% lorem %}。詳情參閱Django文檔。

本章接下來將詳細(xì)描述前面沒有介紹過的 django.contrib 開發(fā)包內(nèi)容。

多個站點(diǎn)

Django 的多站點(diǎn)系統(tǒng)是一種通用框架,它讓你可以在同一個數(shù)據(jù)庫和同一個Django項(xiàng)目下操作多個網(wǎng)站。 這是一個抽象概念,理解起來可能有點(diǎn)困難,因此我們從幾個讓它能派上用場的實(shí)際情景入手。

情景1:多站點(diǎn)間復(fù)用數(shù)據(jù)

正如我們在第一章里所講,Django 構(gòu)建的網(wǎng)站 LJWorld.com 和 Lawrance.com 是用由同一個新聞組織控制的: 肯薩斯州勞倫斯市的 勞倫斯日報(bào)世界 報(bào)紙。 LJWorld.com 主要做新聞,而 Lawrence.com 關(guān)注本地娛樂。 然而有時(shí),編輯可能需要把一篇文章發(fā)布到 兩個 網(wǎng)站上。

解決此問題的死腦筋方法可能是使用每個站點(diǎn)分別使用不同的數(shù)據(jù)庫,然后要求站點(diǎn)維護(hù)者把同一篇文章發(fā)布兩次: 一次為 LJWorld.com,另一次為Lawrence.com。 但這對站點(diǎn)管理員來說是低效率的,而且為同一篇文章在數(shù)據(jù)庫里保留多個副本也顯得多余。

更好的解決方案? 兩個網(wǎng)站用的是同一個文章數(shù)據(jù)庫,并將每一篇文章與一個或多個站點(diǎn)用多對多關(guān)系關(guān)聯(lián)起來。 Django 站點(diǎn)框架提供數(shù)據(jù)庫表來記載哪些文章可以被關(guān)聯(lián)。 它是一個把數(shù)據(jù)與一個或多個站點(diǎn)關(guān)聯(lián)起來的鉤子。

情景2:把網(wǎng)站的名字/域名保存在一個地方

LJWorld.com 和 Lawrence.com 都有郵件提醒功能,使讀者注冊后可以在新聞發(fā)生后立即收到通知。 這是一種完美的的機(jī)制: 某讀者提交了注冊表單,然后馬上就受到一封內(nèi)容是“感謝您的注冊”的郵件。

把這個注冊過程的代碼實(shí)現(xiàn)兩遍顯然是低效、多余的,因此兩個站點(diǎn)在后臺使用相同的代碼。 但感謝注冊的通知在兩個網(wǎng)站中需要不同。 通過使用 Site 對象,我們通過使用當(dāng)前站點(diǎn)的 name (例如 'LJWorld.com' )和domain (例如 'www.ljworld.com' )可以把感謝通知抽提出來。

Django 的多站點(diǎn)框架為你提供了一個位置來存儲 Django 項(xiàng)目中每個站點(diǎn)的 name 和 domain ,這意味著你可以用同樣的方法來重用這些值。

如何使用多站點(diǎn)框架

多站點(diǎn)框架與其說是一個框架,不如說是一系列約定。 所有的一切都基于兩個簡單的概念:

  • 位于 django.contrib.sites 的 Site 模型有 domain 和 name 兩個字段。

  • SITE_ID 設(shè)置指定了與特定配置文件相關(guān)聯(lián)的 Site 對象之?dāng)?shù)據(jù)庫 ID。

如何運(yùn)用這兩個概念由你決定,但 Django 是通過幾個簡單的約定自動使用的。

安裝多站點(diǎn)應(yīng)用要執(zhí)行以下幾個步驟:

  1. 將 'django.contrib.sites' 加入到 INSTALLED_APPS 中。

  2. 運(yùn)行 manage.py syncdb 命令將 django_site 表安裝到數(shù)據(jù)庫中。 這樣也會建立默認(rèn)的站點(diǎn)對象,域名為 example.com。

  3. 把example.com改成你自己的域名,然后通過Django admin站點(diǎn)或Python API來添加其他Site對象。 為該 Django 項(xiàng)目支撐的每個站(或域)創(chuàng)建一個 Site 對象。

  4. 在每個設(shè)置文件中定義一個 SITE_ID 變量。 該變量值應(yīng)當(dāng)是該設(shè)置文件所支撐的站點(diǎn)Site 對象的數(shù)據(jù)庫 ID。

多站點(diǎn)框架的功能

下面幾節(jié)講述的是用多站點(diǎn)框架能夠完成的幾項(xiàng)工作。

多個站點(diǎn)的數(shù)據(jù)重用

正如在情景一中所解釋的,要在多個站點(diǎn)間重用數(shù)據(jù),僅需在模型中為 Site 添加一個 多對多字段 即可,例如:

from django.db import models
from django.contrib.sites.models import Site

class Article(models.Model):
    headline = models.CharField(max_length=200)
    # ...
    sites = models.ManyToManyField(Site)

這是在數(shù)據(jù)庫中為多個站點(diǎn)進(jìn)行文章關(guān)聯(lián)操作的基礎(chǔ)步驟。 在適當(dāng)?shù)奈恢檬褂迷摷夹g(shù),你可以在多個站點(diǎn)中重復(fù)使用同一段 Django 視圖代碼。 繼續(xù) Article 模型范例,下面是一個可能的 article_detail 視圖:

from django.conf import settings
from django.shortcuts import get_object_or_404
from mysite.articles.models import Article

def article_detail(request, article_id):
    a = get_object_or_404(Article, id=article_id, sites__id=settings.SITE_ID)
    # ...

該視圖方法是可重用的,因?yàn)樗鶕?jù) SITE_ID 設(shè)置的值動態(tài)檢查 articles 站點(diǎn)。

例如, LJWorld.coms 設(shè)置文件中有有個 SITE_ID 設(shè)置為 1 ,而 Lawrence.coms 設(shè)置文件中有個 SITE_ID 設(shè)置為 2 。如果該視圖在 LJWorld.coms 處于激活狀態(tài)時(shí)被調(diào)用,那么它將把查找范圍局限于站點(diǎn)列表包括 LJWorld.com 在內(nèi)的文章。

將內(nèi)容與單一站點(diǎn)相關(guān)聯(lián)

同樣,你也可以使用 外鍵 在多對一關(guān)系中將一個模型關(guān)聯(lián)到 Site 模型。

舉例來說,如果某篇文章僅僅能夠出現(xiàn)在一個站點(diǎn)上,你可以使用下面這樣的模型:

from django.db import models
from django.contrib.sites.models import Site

class Article(models.Model):
    headline = models.CharField(max_length=200)
    # ...
    site = models.ForeignKey(Site)

這與前一節(jié)中介紹的一樣有益。

從視圖鉤掛當(dāng)前站點(diǎn)

在底層,通過在 Django 視圖中使用多站點(diǎn)框架,你可以讓視圖根據(jù)調(diào)用站點(diǎn)不同而完成不同的工作,例如:

from django.conf import settings

def my_view(request):
    if settings.SITE_ID == 3:
        # Do something.
    else:
        # Do something else.

當(dāng)然,像那樣對站點(diǎn) ID 進(jìn)行硬編碼是比較難看的。 略為簡潔的完成方式是查看當(dāng)前的站點(diǎn)域:

from django.conf import settings
from django.contrib.sites.models import Site

def my_view(request):
    current_site = Site.objects.get(id=settings.SITE_ID)
    if current_site.domain == 'foo.com':
        # Do something
    else:
        # Do something else.

從 Site 對象中獲取 settings.SITE_ID 值的做法比較常見,因此 Site 模型管理器 (Site.objects ) 具備一個get_current() 方法。 下面的例子與前一個是等效的:

from django.contrib.sites.models import Site

def my_view(request):
    current_site = Site.objects.get_current()
    if current_site.domain == 'foo.com':
        # Do something
    else:
        # Do something else.

注意

在這個最后的例子里,你不用導(dǎo)入 django.conf.settings 。

獲取當(dāng)前域用于呈現(xiàn)

正如情景二中所解釋的那樣,依據(jù)DRY原則(不做重復(fù)工作),你只需在一個位置儲存站名和域名,然后引用當(dāng)前Site 對象的 name 和 domain 。例如: 例如:

from django.contrib.sites.models import Site
from django.core.mail import send_mail

def register_for_newsletter(request):
    # Check form values, etc., and subscribe the user.
    # ...
    current_site = Site.objects.get_current()
    send_mail('Thanks for subscribing to %s alerts' % current_site.name,
        'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name,
        'editor@%s' % current_site.domain,
        [user_email])
    # ...

繼續(xù)我們正在討論的 LJWorld.com 和 Lawrence.com 例子,在Lawrence.com 該郵件的標(biāo)題行是“感謝注冊 Lawrence.com 提醒信件”。 在 LJWorld.com ,該郵件標(biāo)題行是“感謝注冊 LJWorld.com 提醒信件”。 這種站點(diǎn)關(guān)聯(lián)行為方式對郵件信息主體也同樣適用。

完成這項(xiàng)工作的一種更加靈活(但更重量級)的方法是使用 Django 的模板系統(tǒng)。 假定 Lawrence.com 和 LJWorld.com 各自擁有不同的模板目錄( TEMPLATE_DIRS ),你可將工作輕松地轉(zhuǎn)交給模板系統(tǒng),如下所示:

from django.core.mail import send_mail
from django.template import loader, Context

def register_for_newsletter(request):
    # Check form values, etc., and subscribe the user.
    # ...
    subject = loader.get_template('alerts/subject.txt').render(Context({}))
    message = loader.get_template('alerts/message.txt').render(Context({}))
    send_mail(subject, message, 'do-not-reply@example.com', [user_email])
    # ...

本例中,你不得不在 LJWorld.com 和 Lawrence.com 的模板目錄中都創(chuàng)建一份 subject.txt 和 message.txt模板。 正如之前所說,該方法帶來了更大的靈活性,但也帶來了更多復(fù)雜性。

盡可能多的利用 Site 對象是減少不必要的復(fù)雜、冗余工作的好辦法。

當(dāng)前站點(diǎn)管理器

如果 站點(diǎn) 在你的應(yīng)用中扮演很重要的角色,請考慮在你的模型中使用方便的 CurrentSiteManager 。 這是一個模型管理器(見第十章),它會自動過濾使其只包含與當(dāng)前站點(diǎn)相關(guān)聯(lián)的對象。

通過顯示地將 CurrentSiteManager 加入模型中以使用它。 例如:

from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager

class Photo(models.Model):
    photo = models.FileField(upload_to='/home/photos')
    photographer_name = models.CharField(max_length=100)
    pub_date = models.DateField()
    site = models.ForeignKey(Site)
    objects = models.Manager()
    on_site = CurrentSiteManager()

通過該模型, Photo.objects.all() 將返回?cái)?shù)據(jù)庫中所有的 Photo 對象,而 Photo.on_site.all() 僅根據(jù)SITE_ID 設(shè)置返回與當(dāng)前站點(diǎn)相關(guān)聯(lián)的 Photo 對象。

換言之,以下兩條語句是等效的:

Photo.objects.filter(site=settings.SITE_ID)
Photo.on_site.all()

CurrentSiteManager 是如何知道 Photo 的哪個字段是 Site 呢?缺省情況下,它會查找一個叫做 site 的字段。如果你的模型包含了名字不是site的_外鍵_或者多對多關(guān)聯(lián),你需要把它作為參數(shù)傳給CurrentSiteManager以顯示指明。下面的模型擁有一個publish_on字段:

from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager

class Photo(models.Model):
    photo = models.FileField(upload_to='/home/photos')
    photographer_name = models.CharField(max_length=100)
    pub_date = models.DateField()
    publish_on = models.ForeignKey(Site)
    objects = models.Manager()
    on_site = CurrentSiteManager('publish_on')

如果試圖使用 CurrentSiteManager 并傳入一個不存在的字段名, Django 將引發(fā)一個 ValueError 異常。

注意

即便是已經(jīng)使用了 CurrentSiteManager ,你也許還想在模型中擁有一個正常的(非站點(diǎn)相關(guān))的 管理器 。正如在附錄 B 中所解釋的,如果你手動定義了一個管理器,那么 Django 不會為你創(chuàng)建全自動的objects = models.Manager() 管理器。

同樣,Django 的特定部分(即 Django 超級管理站點(diǎn)和通用視圖)使用在模型中定義 的_第一個_管理器,因此如果希望管理站點(diǎn)能夠訪問所有對象(而不是僅僅站點(diǎn)特有對象),請于定義 CurrentSiteManager 之前在模型中放入 objects = models.Manager() 。

Django如何使用多站點(diǎn)框架

盡管并不是必須的,我們還是強(qiáng)烈建議使用多站點(diǎn)框架,因?yàn)?Django 在幾個地方利用了它。 即使只用 Django 來支持單個網(wǎng)站,你也應(yīng)該花一點(diǎn)時(shí)間用 domain 和 name 來創(chuàng)建站點(diǎn)對象,并將 SITE_ID 設(shè)置指向它的 ID 。

以下講述的是 Django 如何使用多站點(diǎn)框架:

  • 在重定向框架中(見后面的重定向一節(jié)),每一個重定向?qū)ο蠖寂c一個特定站點(diǎn)關(guān)聯(lián)。 當(dāng) Django 搜索重定向的時(shí)候,它會考慮當(dāng)前的 SITE_ID 。

  • 在注冊框架中,每個注釋都與特定站點(diǎn)相關(guān)。 每個注釋被顯示時(shí),其 site 被設(shè)置為當(dāng)前的 SITE_ID ,而當(dāng)通過適當(dāng)?shù)哪0鍢?biāo)簽列出注釋時(shí),只有當(dāng)前站點(diǎn)的注釋將會顯示。

  • 在 flatpages 框架中 (參見后面的 Flatpages 一節(jié)),每個 flatpage 都與特定的站點(diǎn)相關(guān)聯(lián)。 創(chuàng)建 flatpage 時(shí),你都將指定它的 site ,而 flatpage 中間件在獲取 flatpage 以顯示它的過程中,將查看當(dāng)前的 SITE_ID 。

  • 在 syndication 框架中(參閱第 13 章), title 和 description 的模板會自動訪問變量 {{ site }} ,它其實(shí)是代表當(dāng)前站點(diǎn)的 Site 對象。 而且,如果你不指定一個合格的domain的話,提供目錄URL的鉤子將會使用當(dāng)前“Site”對象的domain。

  • 在權(quán)限框架中(參見十四章),視圖django.contrib.auth.views.login把當(dāng)前Site名字和對象分別以{{ site_name }}和{{ site }}的形式傳給了模板。

Flatpages(簡單頁面)

盡管通常情況下總是搭建運(yùn)行數(shù)據(jù)庫驅(qū)動的 Web 應(yīng)用,有時(shí)你還是需要添加一兩張一次性的靜態(tài)頁面,例如“關(guān)于”頁面,或者“隱私策略”頁面等等。 可以用像 Apache 這樣的標(biāo)準(zhǔn)Web服務(wù)器來處理這些靜態(tài)頁面,但卻會給應(yīng)用帶來一些額外的復(fù)雜性,因?yàn)槟惚仨毑傩脑趺磁渲?Apache,還要設(shè)置權(quán)限讓整個團(tuán)隊(duì)可以修改編輯這些文件,而且你還不能使用 Django 模板系統(tǒng)來統(tǒng)一這些頁面的風(fēng)格。

這個問題的解決方案是使用位于 django.contrib.flatpages 開發(fā)包中的 Django 簡單頁面(flatpages)應(yīng)用程序。該應(yīng)用讓你能夠通過 Django 管理站點(diǎn)來管理這些一次性的頁面,還可以讓你使用 Django 模板系統(tǒng)指定它們使用哪個模板。 它在后臺使用Django模型,這意味著它把頁面項(xiàng)別的數(shù)據(jù)一樣保存在數(shù)據(jù)庫中,也就是說你可以使用標(biāo)準(zhǔn)Django數(shù)據(jù)庫API來存取頁面。

簡單頁面以它們的 URL 和站點(diǎn)為鍵值。 當(dāng)創(chuàng)建簡單頁面時(shí),你指定它與哪個URL以及和哪個站點(diǎn)相關(guān)聯(lián) 。 (有關(guān)站點(diǎn)的更多信息,請查閱”多站點(diǎn)“一節(jié)。)

使用簡單頁面

安裝簡單頁面應(yīng)用程序必須按照下面的步驟:

  1. 添加 'django.contrib.flatpages' 到 INSTALLED_APPS 設(shè)置。django.contrib.flatpages依賴django.contrib.sites,所以確保它們都在INSTALLED_APPS里。

  2. 將 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' 添加到 MIDDLEWARE_CLASSES設(shè)置中。

  3. 運(yùn)行 manage.py syncdb 命令在數(shù)據(jù)庫中創(chuàng)建必需的兩個表。

簡單頁面應(yīng)用程序在數(shù)據(jù)庫中創(chuàng)建兩個表: django_flatpage 和 django_flatpage_sites 。 django_flatpage只是將 URL 映射到標(biāo)題和一段文本內(nèi)容。 django_flatpage_sites 是一個多對多表,用于關(guān)聯(lián)某個簡單頁面以及一個或多個站點(diǎn)。

該應(yīng)用捆綁的 FlatPage 模型在 django/contrib/flatpages/models.py 進(jìn)行定義,如下所示:

from django.db import models
from django.contrib.sites.models import Site

class FlatPage(models.Model):
    url = models.CharField(max_length=100, db_index=True)
    title = models.CharField(max_length=200)
    content = models.TextField(blank=True)
    enable_comments = models.BooleanField()
    template_name = models.CharField(max_length=70, blank=True)
    registration_required = models.BooleanField()
    sites = models.ManyToManyField(Site)

讓我們逐項(xiàng)看看這些字段的含義:

  • url : 該簡單頁面所處的 URL,不包括域名,但是包含前導(dǎo)斜杠 (例如 /about/contact/ )。

  • title : 簡單頁面的標(biāo)題。 框架不對它作任何特殊處理。 由你通過模板來顯示它。

  • content : 簡單頁面的內(nèi)容 (即 HTML 頁面)。 框架不對它作任何特殊處理。 由你負(fù)責(zé)使用模板來顯示。

  • enable_comments : 是否允許該簡單頁面使用評論。 框架不對它作任何特殊處理。 你可在模板中檢查該值并根據(jù)需要顯示評論窗體。

  • template_name : 用來解析該簡單頁面的模板名稱。 這是一個可選項(xiàng);如果未指定模板或該模板不存在,系統(tǒng)會退而使用默認(rèn)模板 flatpages/default.html 。

  • registration_required : 是否注冊用戶才能查看此簡單頁面。 該設(shè)置項(xiàng)集成了 Djangos 驗(yàn)證/用戶框架,該框架于第十四章詳述。

  • sites : 該簡單頁面放置的站點(diǎn)。 該項(xiàng)設(shè)置集成了 Django 多站點(diǎn)框架,該框架在本章的“多站點(diǎn)”一節(jié)中有所闡述。

你可以通過 Django 超級管理界面或者 Django 數(shù)據(jù)庫 API 來創(chuàng)建簡單頁面。 要了解更多內(nèi)容,請查閱“添加、修改和刪除簡單頁面”一節(jié)。

一旦簡單頁面創(chuàng)建完成, FlatpageFallbackMiddleware 將完成(剩下)所有的工作。 每當(dāng) Django 引發(fā) 404 錯誤,作為最后的辦法,該中間件將根據(jù)所請求的 URL 檢查簡單頁面數(shù)據(jù)庫。 確切地說,它將使用所指定的 URL以及 SITE_ID 設(shè)置對應(yīng)的站點(diǎn) ID 查找一個簡單頁面。

如果找到一個匹配項(xiàng),它將載入該簡單頁面的模板(如果沒有指定的話,將使用默認(rèn)模板flatpages/default.html )。 同時(shí),它把一個簡單的上下文變量flatpage(一個簡單頁面對象)傳遞給模板。 模板解析過程中,它實(shí)際用的是RequestContext。

如果 FlatpageFallbackMiddleware 沒有找到匹配項(xiàng),該請求繼續(xù)如常處理。

注意

該中間件僅在發(fā)生 404 (頁面未找到)錯誤時(shí)被激活,而不會在 500 (服務(wù)器錯誤)或其他錯誤響應(yīng)時(shí)被激活。 還要注意的是必須考慮 MIDDLEWARE_CLASSES 的順序問題。 通常,你可以把 FlatpageFallbackMiddleware放在列表最后,因?yàn)樗亲詈蟮霓k法。

添加、修改和刪除簡單頁面

可以用兩種方式增加、變更或刪除簡單頁面:

通過超級管理界面

如果已經(jīng)激活了自動的 Django 超級管理界面,你將會在超級管理頁面的首頁看到有個 Flatpages 區(qū)域。 你可以像編輯系統(tǒng)中其它對象那樣編輯簡單頁面。

通過 Python API

前面已經(jīng)提到,簡單頁面表現(xiàn)為 django/contrib/flatpages/models.py 中的標(biāo)準(zhǔn) Django 模型。這樣,你就可以使用Django數(shù)據(jù)庫API來存取簡單頁面對象,例如:

>>> from django.contrib.flatpages.models import FlatPage
>>> from django.contrib.sites.models import Site
>>> fp = FlatPage.objects.create(
...     url='/about/',
...     title='About',
...     content='About this site...',
...     enable_comments=False,
...     template_name='',
...     registration_required=False,
... )
>>> fp.sites.add(Site.objects.get(id=1))
>>> FlatPage.objects.get(url='/about/')

使用簡單頁面模板

缺省情況下,系統(tǒng)使用模板 flatpages/default.html 來解析簡單頁面,但你也可以通過設(shè)定 FlatPage 對象的template_name 字段來更改特定簡單頁面的模板。

你必須自己創(chuàng)建 flatpages/default.html 模板。 只需要在模板目錄創(chuàng)建一個 flatpages 目錄,并把default.html 文件置于其中。

簡單頁面模板只接受有一個上下文變量—— flatpage ,也就是該簡單頁面對象。

以下是一個 flatpages/default.html 模板范例:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
    "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>{{ flatpage.title }}</title>
</head>
<body>
{{ flatpage.content|safe }}
</body>
</html>

注意我們使用了safe模板過濾器來允許flatpage.content引入原始HTML而不必轉(zhuǎn)義。

重定向

通過將重定向存儲在數(shù)據(jù)庫中并將其視為 Django 模型對象,Django 重定向框架讓你能夠輕松地管理它們。 比如說,你可以通過重定向框架告訴Django,把任何指向 /music/ 的請求重定向到 /sections/arts/music/ 。當(dāng)你需要在站點(diǎn)中移動一些東西時(shí),這項(xiàng)功能就派上用場了——網(wǎng)站開發(fā)者應(yīng)該窮盡一切辦法避免出現(xiàn)壞鏈接。

使用重定向框架

安裝重定向應(yīng)用程序必須遵循以下步驟:

  1. 將 'django.contrib.redirects' 添加到 INSTALLED_APPS 設(shè)置中。

  2. 將 'django.contrib.redirects.middleware.RedirectFallbackMiddleware' 添加到 MIDDLEWARE_CLASSES設(shè)置中。

  3. 運(yùn)行 manage.py syncdb 命令將所需的表添加到數(shù)據(jù)庫中。

manage.py syncdb 在數(shù)據(jù)庫中創(chuàng)建了一個 django_redirect 表。 這是一個簡單的查詢表,只有site_id、old_path和new_path三個字段。

你可以通過 Django 超級管理界面或者 Django 數(shù)據(jù)庫 API 來創(chuàng)建重定向。 要了解更多信息,請參閱“增加、變更和刪除重定向”一節(jié)。

一旦創(chuàng)建了重定向, RedirectFallbackMiddleware 類將完成所有的工作。 每當(dāng) Django 應(yīng)用引發(fā)一個 404 錯誤,作為終極手段,該中間件將為所請求的 URL 在重定向數(shù)據(jù)庫中進(jìn)行查找。 確切地說,它將使用給定的old_path 以及 SITE_ID 設(shè)置對應(yīng)的站點(diǎn) ID 查找重定向設(shè)置。 (查閱前面的“多站點(diǎn)”一節(jié)可了解關(guān)于SITE_ID 和多站點(diǎn)框架的更多細(xì)節(jié)) 然后,它將執(zhí)行以下兩個步驟:

  • 如果找到了匹配項(xiàng),并且 new_path 非空,它將重定向到 new_path 。

  • 如果找到了匹配項(xiàng),但 new_path 為空,它將發(fā)送一個 410 (Gone) HTTP 頭信息以及一個空(無內(nèi)容)響應(yīng)。

  • 如果未找到匹配項(xiàng),該請求將如常處理。

該中間件僅為 404 錯誤激活,而不會為 500 錯誤或其他任何狀態(tài)碼的響應(yīng)所激活。

注意必須考慮 MIDDLEWARE_CLASSES 的順序。 通常,你可以將 RedirectFallbackMiddleware 放置在列表的最后,因?yàn)樗且环N終極手段。

注意

如果同時(shí)使用重定向和簡單頁面回退中間件, 必須考慮先檢查其中的哪一個(重定向或簡單頁面)。 我們建議將簡單頁面放在重定向之前(因此將簡單頁面中間件放置在重定向中間件之前),但你可能有不同想法。

增加、變更和刪除重定向

你可以兩種方式增加、變更和刪除重定向:

通過管理界面

如果已經(jīng)激活了全自動的 Django 超級管理界面,你應(yīng)該能夠在超級管理首頁看到重定向區(qū)域。 可以像編輯系統(tǒng)中其它對象一樣編輯重定向。

同過Python API

重定向表現(xiàn)為django/contrib/redirects/models.py 中的一個標(biāo)準(zhǔn) Django 模型。因此,你可以通過Django數(shù)據(jù)庫API來存取重定向?qū)ο螅纾?/p>

>>> from django.contrib.redirects.models import Redirect
>>> from django.contrib.sites.models import Site
>>> red = Redirect.objects.create(
...     site=Site.objects.get(id=1),
...     old_path='/music/',
...     new_path='/sections/arts/music/',
... )
>>> Redirect.objects.get(old_path='/music/')
 /sections/arts/music/>

CSRF 防護(hù)

django.contrib.csrf 開發(fā)包能夠防止遭受跨站請求偽造攻擊 (CSRF).

CSRF, 又叫會話跳轉(zhuǎn),是一種網(wǎng)站安全攻擊技術(shù)。 當(dāng)某個惡意網(wǎng)站在用戶未察覺的情況下將其從一個已經(jīng)通過身份驗(yàn)證的站點(diǎn)誘騙至一個新的 URL 時(shí),這種攻擊就發(fā)生了,因此它可以利用用戶已經(jīng)通過身份驗(yàn)證的狀態(tài)。 乍一看,要理解這種攻擊技術(shù)比較困難,因此我們在本節(jié)將使用兩個例子來說明。

一個簡單的 CSRF 例子

假定你已經(jīng)登錄到 example.com 的網(wǎng)頁郵件賬號。該網(wǎng)站有一個指向example.com/logout的注銷按鈕。就是說,注銷其實(shí)就是訪問example.com/logout。

通過在(惡意)網(wǎng)頁上用隱藏一個指向 URL example.com/logout 的  ,惡意網(wǎng)站可以強(qiáng)迫你訪問該 URL 。因此,如果你登錄 example.com 的網(wǎng)頁郵件賬號之后,訪問了帶有指向 example.com/logout 之  的惡意站點(diǎn),訪問該惡意頁面的動作將使你登出 example.com 。 Thus, if you’re logged in to the example.comwebmail account and visit the malicious page that has an  to example.com/logout , the act of visiting the malicious page will log you out from example.com .

很明顯,登出一個郵件網(wǎng)站也不是什么嚴(yán)重的安全問題。但是同樣的攻擊可能針對任何相信用戶的站點(diǎn),比如在線銀行和電子商務(wù)網(wǎng)站。這樣的話可能在用戶不知情的情況下就下訂單付款了。

稍微復(fù)雜一點(diǎn)的CSRF例子

在上一個例子中, example.com 應(yīng)該負(fù)部分責(zé)任,因?yàn)樗试S通過 HTTP GET 方法進(jìn)行狀態(tài)變更(即登入和登出)。 如果對服務(wù)器的狀態(tài)變更要求使用 HTTP POST 方法,情況就好得多了。 但是,即便是強(qiáng)制要求使用POST 方法進(jìn)行狀態(tài)變更操作也易受到 CSRF 攻擊。

假設(shè) example.com 對登出功能進(jìn)行了升級,登出  按鈕是通過一個指向 URL example.com/logout 的 POST動作完成,同時(shí)在  中加入了以下隱藏的字段:

<input type="hidden" name="confirm" value="true">

這就確保了用簡單的指向example.com/logout的POST 不會讓用戶登出;要讓用戶登出,用戶必須通過 POST 向example.com/logout 發(fā)送請求 并且發(fā)送一個值為’true’的POST變量。 confirm。

盡管增加了額外的安全機(jī)制,這種設(shè)計(jì)仍然會遭到 CSRF 的攻擊——惡意頁面僅需一點(diǎn)點(diǎn)改進(jìn)而已。 攻擊者可以針對你的站點(diǎn)設(shè)計(jì)整個表單,并將其藏身于一個不可見的  中,然后使用 Javascript 自動提交該表單。

防止 CSRF

那么,是否可以讓站點(diǎn)免受這種攻擊呢? 第一步,首先確保所有 GET 方法沒有副作用。 這樣以來,如果某個惡意站點(diǎn)將你的頁面包含為  ,它將不會產(chǎn)生負(fù)面效果。

該技術(shù)沒有考慮 POST 請求。 第二步就是給所有 POST 的form標(biāo)簽一個隱藏字段,它的值是保密的并根據(jù)用戶進(jìn)程的 ID 生成。 這樣,從服務(wù)器端訪問表單時(shí),可以檢查該保密的字段。不吻合時(shí)可以引發(fā)一個錯誤。

這正是 Django CSRF 防護(hù)層完成的工作,正如下面的小節(jié)所介紹的。

使用CSRF中間件

django.contrib.csrf 開發(fā)包只有一個模塊: middleware.py 。該模塊包含了一個 Django 中間件類——CsrfMiddleware ,該類實(shí)現(xiàn)了 CSRF 防護(hù)功能。

在設(shè)置文件中將 'django.contrib.csrf.middleware.CsrfMiddleware' 添加到 MIDDLEWARE_CLASSES 設(shè)置中可激活 CSRF 防護(hù)。 該中間件必須在 SessionMiddleware 之后 執(zhí)行,因此在列表中 CsrfMiddleware 必須出現(xiàn)在SessionMiddleware 之前 (因?yàn)轫憫?yīng)中間件是自后向前執(zhí)行的)。 同時(shí),它也必須在響應(yīng)被壓縮或解壓之前對響應(yīng)結(jié)果進(jìn)行處理,因此 CsrfMiddleware 必須在 GZipMiddleware 之后執(zhí)行。一旦將它添加到MIDDLEWARE_CLASSES設(shè)置中,你就完成了工作。 參見第十五章的“MIDDLEWARE_CLASSES順序”小節(jié)以了解更多。

如果感興趣的話,下面是 CsrfMiddleware 的工作模式。 它完成以下兩項(xiàng)工作:

  1. 它修改當(dāng)前處理的請求,向所有的 POST 表單增添一個隱藏的表單字段,使用名稱是 csrfmiddlewaretoken,值為當(dāng)前會話 ID 加上一個密鑰的散列值。 如果未設(shè)置會話 ID ,該中間件將 不會 修改響應(yīng)結(jié)果,因此對于未使用會話的請求來說性能損失是可以忽略的。

  2. 對于所有含會話 cookie 集合的傳入 POST 請求,它將檢查是否存在 csrfmiddlewaretoken 及其是否正確。 如果不是的話,用戶將會收到一個 403 HTTP 錯誤。 403 錯誤頁面的內(nèi)容是檢測到了跨域請求偽裝。 終止請求。

該步驟確保只有源自你的站點(diǎn)的表單才能將數(shù)據(jù) POST 回來。

該中間件特意只針對 HTTP POST 請求(以及對應(yīng)的 POST 表單)。 如我們所解釋的,永遠(yuǎn)不應(yīng)該因?yàn)槭褂昧薌ET 請求而產(chǎn)生負(fù)面效應(yīng),你必須自己來確保這一點(diǎn)。

未使用會話 cookie 的 POST 請求無法受到保護(hù),但它們也不 需要 受到保護(hù),因?yàn)閻阂饩W(wǎng)站可用任意方法來制造這種請求。

為了避免轉(zhuǎn)換非 HTML 請求,中間件在編輯響應(yīng)結(jié)果之前對它的 Content-Type 頭標(biāo)進(jìn)行檢查。 只有標(biāo)記為text/html 或 application/xml+xhtml 的頁面才會被修改。

CSRF中間件的局限性

CsrfMiddleware 的運(yùn)行需要 Django 的會話框架。 (參閱第 14 章了解更多關(guān)于會話的內(nèi)容。)如果你使用了自定義會話或者身份驗(yàn)證框架手動管理會話 cookies,該中間件將幫不上你的忙。

如果你的應(yīng)用程序以某種非常規(guī)的方法創(chuàng)建 HTML 頁面(例如:在 Javascript 的document.write語句中發(fā)送 HTML 片段),你可能會繞開了向表單添加隱藏字段的過濾器。 在此情況下,表單提交永遠(yuǎn)無法成功。 (這是因?yàn)樵陧撁姘l(fā)送到客戶端之前,CsrfMiddleware使用正則表達(dá)式來添加csrfmiddlewaretoken字段到你的HTML中,而正則表達(dá)式不能處理不規(guī)范的HTML。)如果你懷疑出現(xiàn)了這樣的問題。使用你瀏覽器的查看源代碼功能以確定csrfmiddlewaretoken是否插入到了表單中。

想了解更多關(guān)于 CSRF 的信息和例子的話,可以訪問 http://en.wikipedia.org/wiki/CSRF 。

人性化數(shù)據(jù)

包django.contrib.humanize包含了一些是數(shù)據(jù)更人性化的模板過濾器。 要激活這些過濾器,請把'django.contrib.humanize'加入到你的INSTALLED_APPS中。完成之后,向模版了加入{% load humanize %}就可以使用下面的過濾器了。

apnumber

對于 1 到 9 的數(shù)字,該過濾器返回了數(shù)字的拼寫形式。 否則,它將返回?cái)?shù)字。 這遵循的是美聯(lián)社風(fēng)格。

舉例:

  • 1 變成 one 。

  • 2 變成 two 。

  • 10 變成 10 。

你可以傳入一個整數(shù)或者表示整數(shù)的字符串。

intcomma

該過濾器將整數(shù)轉(zhuǎn)換為每三個數(shù)字用一個逗號分隔的字符串。

例子:

  • 4500 變成 4,500 。

  • 45000 變成 45,000 。

  • 450000 變成 450,000 。

  • 4500000 變成 4,500,000 。

可以傳入整數(shù)或者表示整數(shù)的字符串。

intword

該過濾器將一個很大的整數(shù)轉(zhuǎn)換成友好的文本表示方式。 它對于超過一百萬的數(shù)字最好用。

例子:

  • 1000000 變成 1.0 million 。

  • 1200000 變成 1.2 million 。

  • 1200000000 變成 1.2 billion 。

最大支持不超過一千的五次方(1,000,000,000,000,000)。

可以傳入整數(shù)或者表示整數(shù)的字符串。

ordinal

該過濾器將整數(shù)轉(zhuǎn)換為序數(shù)詞的字符串形式。

例子:

  • 1 變成 1st 。

  • 2 變成 2nd 。

  • 3 變成 3rd 。

  • 254變成254th。

可以傳入整數(shù)或者表示整數(shù)的字符串。

標(biāo)記過濾器

包django.contrib.markup包含了一些列Django模板過濾器,每一個都實(shí)現(xiàn)了一中通用的標(biāo)記語言。

每種情形下,過濾器都期望字符串形式的格式化標(biāo)記,并返回表示標(biāo)記文本的字符串。 例如:textile過濾器吧Textile格式的文本轉(zhuǎn)換為HTML。

{% load markup %}
{{ object.content|textile }}

要激活這些過濾器,僅需將 'django.contrib.markup' 添加到 INSTALLED_APPS 設(shè)置中。 一旦完成了該項(xiàng)工作,在模板中通過 {% load markup %} 就能使用這些過濾器。 要想掌握更多信息的話,可閱讀django/contrib/markup/templatetags/markup.py. 內(nèi)的源代碼。

下一章

這些繼承框架(CSRF、身份驗(yàn)證系統(tǒng)等等)通過提供 中間件 來實(shí)現(xiàn)其奇妙的功能。中間件是在請求之前/后執(zhí)行的可以修改請求和響應(yīng)的代碼,它擴(kuò)展了框架。 在下一章,我們將介紹Django的中間件并解釋怎樣寫出自己的中間件。

關(guān)閉
程序員人生
主站蜘蛛池模板: 啪一啪在线视频 | 国产xxx护士爽免费看 | 动漫精品一级毛片动漫 | 免费观看欧美一级高清 | 欧美成人精品 | 亚洲区欧美区小说区图片区 | 免费观看欧美成人1314色 | 日本欧美一区二区三区不卡视频 | 国产亚洲欧美一区二区 | 网址在线| 六九视频在线观看 | 国产成人综合亚洲欧美在 | 亚洲一区二区三区高清不卡 | 欧美综合精品 | 欧美一欧美一级毛片 | a毛片免费看 | 老司机午夜免费视频 | 亚洲二区在线视频 | 宇都宫紫苑在线 | 日韩视频在线一区 | 一级毛片免费观看视频 | 国产精品久久1024 | 视频三区精品中文字幕 | 网站在线免费观看 | 亚洲精品一区二区三区在线看 | 国产精品亚洲精品一区二区三区 | 欧美在线观看成人高清视频 | xxxx69欧美hdxxxhd xxxxhd欧美精品 | 羞羞视频免费观看网站 | 波多野结衣在线一区 | 日韩欧美国产另类 | 波多野结衣中文一区二区免费 | 高清不卡免费一区二区三区 | 亚洲成aⅴ人在线观看 | 操你网| 羞羞视频免费入口网站 | 亚洲国产精品久久久久久网站 | japan高清日本乱xxxx | 亚洲精品美女久久久aaa | 国产18在线播放 | 国语对白清晰好大好白在线 |