Django開發——集成的子框架django.contrib

Django開發——集成的子框架django.contrib

Django標準庫

Django的標準庫存放在django.contrib包中。每一個子包都是一個獨立的附加包,這些子包通常都是相互獨立的,不過有些子包須要依賴其餘子包。
django.contrib開發包共有的特性是:就算你將整個django.contrib開發包刪除,你依然可使用Django的基礎功能而不會遇到任何問題。
django.contrib由如下開發包組成:html

  • admin:自動化的站點管理;
  • admindocs:爲Django admin站點提供自動文檔;
  • auth:Django的用戶驗證框架;
  • comments:一個評論應用;
  • contenttypes:一個用於引入文檔類型的框架,每一個安裝的Django模塊做爲一種獨立的文檔類型。
  • csrf:這個模塊用來防護跨站請求僞造;
  • databrowse:幫助你瀏覽數據的一個用;
  • flatpages:一個在數據庫中管理單一HTML內容的模塊;
  • formtools:一些列表處理表單通用模式的高級庫;
  • gis:爲Django提供GIS支持的擴展;
  • humanize:一系列Django模塊過濾器,用於增長數據的人性化。
  • localflavor:針對不一樣國家和文化的混雜代碼段;
  • markup:一系列的Django模板過濾器;
  • redirects:用來管理重定向的框架;
  • sessions:Django會話框架;
  • sitemaps:用來生成網站地圖的XML文件的框架;
  • sites:一個讓你能夠在同一個數據庫與Django安裝中管理多個網站的框架。
  • syndication:一個用RSS和Atom來生成聚合訂閱源的框架;
  • webdesign:對設計者很是有用的Django擴展。

如何使用多站點框架
多站點框架:web

  • 位於django.contrib.sites的site模型由domain和name兩個字段。
  • SITE_ID設置指定了與特定配置文件相關聯的site對象之數據庫的ID。

安裝多站點應用要執行如下幾個步驟:數據庫

  • 將‘django.contrib.sites’加入到INSTALLED_APPS中。
  • 運行manage.py syncdb命令將django_site表安裝到數據庫中。這樣也會創建默認的站點對象,域名爲example.com
  • 把example.com改爲本身的域名,而後經過Django admin站點或Python API來添加其餘site對象。爲該Django項目支撐的每一個站點建立一個site對象。
  • 在每一個設置文件中定義一個SITE_ID變量。該變量值應當是該設置文件所支撐的站點Site對象的數據庫ID。

多站點框架的功能

多個站點的數據重用
要在多各站點間重用數據,僅需在模型中爲site添加一個多對多字段便可:django

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在適當的位置使用這個技術,你能夠在多站點中重度使用統一段Django視圖代碼。服務器

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)
# ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

該視圖方法是可重用的,由於它根據SITE_ID設置的值動態檢查articles站點。
將內容與單一站點相關聯
可使用外鍵在多對一關係中將一個模型關聯到site模型。markdown

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

從視圖鉤掛當前站點
在底層,經過Django視圖中使用多站點框架,可讓視圖根據用站點不一樣而完成不一樣的工做。session

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.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

從site對象中得到settings.SITE_ID值的作法比較常見,所以SIte模型管理具有一個get_current()方法。app

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.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

獲取當前域用於呈現
依據DRY原則(不作重複工做),你只需在一個位置儲存站點和域名,而後引用當前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])
	# ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在Lawrence.com 該郵件的標題行是「感謝註冊Lawrence.com 提醒信件」。 在 LJWorld.com ,該郵件標題行是「感謝註冊 LJWorld.com 提醒信件」。 這種站點關聯行爲方式對郵件信息主體也一樣適用。
完成這項工做的一種更加靈活的方法是使用Django的模板系統。假定Lawrence.com和LJWorld.com擁有各子不一樣的模板目錄,能夠將工做輕鬆地轉交給模板系統。dom

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])
	# ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

當前站點管理器

若是站點在你的應用中扮演很重要的角色,請考慮在你的模型中使用方便的
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Photo.objects.all()將返回數據庫中全部的Photo對象,而Photo.on_site.all()僅根據SITE_ID設置返回與當前站點相關聯的Photo對象。

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

這兩條是等價的。
CurrentSiteManager是如何知道Photo的哪一個字段是Site呢?缺省狀況下,它會查找一個叫作site的字段。若是你的模型包含不是site的外鍵或者多對多關聯,須要把它做爲參數傳給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()
	publish_on = models.ForeignKey(Site)
	objects = models.Manager()
	on_site = CurrentSiteManager('publish_on')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

若是傳入一個不存在的字段名,則會引起異常。
Django的特定部分(即Django超級管理站點和通用視圖)使用在模型中定義的第一個管理器,所以若是但願管理站點可以訪問全部對象,請於定義CurrentSiteManager以前在模型中放入objects=models.Manager().

Django如何使用多站點框架

便是隻用Django來支持單個網站,也應該化一點時間用domain和name來建立站點對象,並將SITE_ID設置指向它的ID。
Django如何使用多站點框架:

  • 在重定向框架中,每個重定向對象都與一個特定站點關聯。當Django搜索重定向的時候,它會考慮當前的SITE_ID.
  • 在註冊框架時,每一個註釋都與特定站點相關。每一個註釋被顯示時,其site被設置爲當前的SITE_ID,而當經過適當的模板標籤列出註釋時,只有當前站點的註釋會顯示。
  • 在flatpages框架中,每一個flatpage都與特定的站點相關聯。建立flatpage時,你將指定它的site,而flatpage中間件在獲取flatpage以顯示它的過程當中。將查詢當前的SITE_ID.
  • 在syndication框架中,title和description的模板會自動訪問變量{{ site }},它實際上是表明當前站點的site對象。若是你不指定一個合格的domain的話,提供目錄URL的鉤子將會使用當前的Site對象的domain。
  • 在權限框架中視圖 django.contrib.auth.views.login 把當前 Site 名字和對象分別以 {{ site_name }} 和 {{ site }} 的形式傳給了模板。

Flatpages(簡單頁面)

儘管一般狀況下老是搭建運行數據庫驅動的Web應用,有時還須要添加一兩張一次性的靜態網頁,例如「關於」或者「隱私策略「頁面等。能夠用像Apache這樣標準的Web服務器來處理這些靜態頁面,但卻會給應用帶來一些額外的複雜性,由於你西須操心怎麼配置Apache,還要設置權限讓整個團隊能夠修改編輯這些文件,並且不能使用Django模板系統來統一這些頁面的風格。
這個問題的解決方案使用位於django.contrib.flatpages開發包中的Django簡單頁面應用程序。該應用讓你可以經過Django管理站點來管理這些一次性的頁面。還可讓你使用Django模板系統指定它們使用哪一個模板。它在後臺使用Django模型,這意味着它把頁面像被的數據同樣保存在數據庫。
簡單頁面以它們的URL和站點爲鍵值,當建立簡單頁面時,你指定與哪一個URL以及和哪一個站點相關聯。
使用簡單頁面
安裝簡單頁面步驟:

  • 添加 ‘django.contrib.flatpages’ 到 INSTALLED_APPS 設置。 django.contrib.flatpages 依賴 django.contrib.sites ,因此確保它們都在INSTALLED_APPS 裏。
  • 將 ‘django.contrib.flatpages.middleware.FlatpageFallbackMiddleware’ 添加到 MIDDLEWARE_CLASSES設置中。
  • 用命令在數據庫中建立必須的兩個表。

django_flatpage只是將URL映射到標題和一段內容。django_flatpage_sites是一個多對多表,用於關聯某個簡單頁面以及一個或多個站點。
該應用捆綁的FlatPage模型在django/contrib/flatpages/models.py中進行定義。

class FlatPage(models.Model):
    url = models.CharField(_('URL'), max_length=100, db_index=True)
    title = models.CharField(_('title'), max_length=200)
    content = models.TextField(_('content'), blank=True)
    enable_comments = models.BooleanField(_('enable comments'), default=False)
    template_name = models.CharField(
        _('template name'),
        max_length=70,
        blank=True,
        help_text=_(
            "Example: 'flatpages/contact_page.html'. If this isn't provided, "
            "the system will use 'flatpages/default.html'."
        ),
    )
    registration_required = models.BooleanField(
        _('registration required'),
        help_text=_("If this is checked, only logged-in users will be able to view the page."),
        default=False,
    )
    sites = models.ManyToManyField(Site, verbose_name=_('sites'))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • url:該簡單頁面所處的URL,不包括域名,單是包含前導斜槓。
  • title:標題;
  • content:內容;
  • enable_comments:是否容許該簡單頁面使用評論;
  • template_name:用來解析該簡單頁面的名稱。可選項,若是未指定模板或者該模板不存在,系統會退而使用默認模板flatpages/defaults.html;
  • registration_required:是否註冊用戶才能看到此頁面。
  • sites:該簡單頁面放置的站點。

一旦完成建立,FlatpageFallbackMiddleware將完成剩下的全部工做。每當Django引起404錯誤,做爲最後的方法該中間件將根據所請求的URL檢查簡單頁面數據庫。具體的說,它將使用所指定的URL以及SITE_ID設置對應的站點ID查找一個簡單的頁面。若是找到一個匹配項,它將載入該簡單頁面的模板,同時它把一個簡單的上下文變量flatpage傳遞給模板,模板解析過程,它實際用的是RequestContext。若是沒有找到匹配項,該請求繼續如常處理。該中間件僅在發生404錯誤是被激活,一般放在最後,由於這是它最後的辦法。
這裏寫圖片描述

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

經過超級管理界面
若是已經激活了自動DJango超級管理界面,你將會在超級管理界面的首頁看到有個Flatpages區域。能夠項編輯系統中其餘對象那樣編輯簡單頁面。

這裏寫圖片描述
經過Python API

>>> from django.contrib.flatpages.models import FlatPage
>>> from django.contrib.sites.models import Site
>>> f=FlatPage.objects.create(
... 	url='/about/',
... 	title='About',
... 	content='<p>About this site...</p>',
... 	enable_comments=False,
... 	templates_name='',
... 	registration_required=Flase
... )
>>> fp.sites.add(Site.objects.get(id=1))
>>> FlatPage.objects.get(url='/about/')
<FlatPage: /about/ ‐‐ About>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

使用簡單頁面模板
缺省狀況下,使用模板flatpages/default.html來解析簡單頁面,也能夠經過設定FlatPage對象的template_name字段來更待特定簡單的模板。
必須本身建立flatpages/default.html模板,只需在模版目錄建立一個flatpages目錄,並把defalut.html文件置於其中。

<html>
<head>
<title>{{ flatpage.title }}</title>
</head>
<body>
{{ flatpage.content|safe }}
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

使用safe模板過濾器容許flatpage.content引入原始HTML而沒必要轉意。

重定向

經過將重定向存儲在數據庫中並將其視爲Djangp模型對象,Django重定向框架讓你可以輕鬆管理它們。
使用重定向框架
步驟:

  • 將 ‘django.contrib.redirects’ 添加到 INSTALLED_APPS 設置中。
  • 將 ‘django.contrib.redirects.middleware.RedirectFallbackMiddleware’ 添加到 MIDDLEWARE_CLASSES設置中。

在數據庫中建立一個django_redirect表。這個表只有site_id,old_path,new_path三個字段。
一旦建立了重定向,RedirectFallbackMiddleware類將完成全部工做。每當Django應用引起一個404錯誤,做爲終極手段,該中間件將爲所請求的URL在重定向數據庫中進行查找。它將使用給定的old_path以及SITE_ID設置對應的站點ID查找重定向設置。

  • 若是找到匹配項,而且new_path非空,它將重定向到new_path;

  • 若是找到匹配項,單new_path爲空,它將發送一個410HTTP頭信息以及一個空嚮應。

  • 若是爲找到匹配項,該請求如常處理。
    該中間件僅爲404錯誤激活,將這個中間件放到列表最後,由於它是終極手段。
    注意:
    若是同時使用重定向和簡單頁面回退中間件,必須考慮先檢查其中的哪個。建議將簡單頁面放在重定向以前。
    增長、變動刪除重定向

  • 經過管理界面:
    若是已經激活了全自動Django超級管理界面,你應該可以在超級管理首頁看到重定向區域。能夠像編輯系統中其餘對象同樣編輯重定向。

  • 重定向表現爲django/contrib/redirects/models.py中的一個標準Django模型。因此能夠經過Django數據庫API來存取重定向對象。

>>> 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/')
<Redirect: /music/ ‐‐‐> /sections/arts/music/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

CSRF防禦

CSRF稱爲跨站請求僞造攻擊,又叫會話跳轉,能夠利用用戶已經經過身分驗證的狀態,誘騙至一個危險的URL。
防止CSRF
第一步,首先確保全部GET方法沒有反作用。這樣一來若是某個惡意站點將你的頁面包含爲iframe它將不會產生負面效果。
第二步就是給全部POST的form標籤一個隱藏字段,它的值是保密的並根據用戶進程的ID生成。這樣從服務端訪問表單時,能夠檢查該保密的字段,不吻合能夠發生一個錯誤。

人性化數據

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

名稱 用法
apnumber 對於1到9的數字,該過濾器返回了數字的拼寫形式。不然,它將返回數字。
intcomma 將整數轉換爲每三個數字用一個逗號分隔的字符串
intword 將一個很大的整數轉換成友好的文本表示方式,1200000 變成1.2million
ordinal 將整數轉換爲序數詞的字符串形式
{% load humanize %}

{{ 1|apnumber }}
<br>
{{ 6|apnumber }}
<br>
{{ 45000000|intcomma }}
<br>
{{ 12000000|intword }}
<br>
{{ 5|ordinal }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

這裏寫圖片描述
標記過濾器
包 django.contrib.markup 包含了一些列Django模板過濾器,每個都實現了一中通用的標記語言。

  • textile:實現了Textile;
  • markdown:實現了Markdown;
  • restructuredtext:實現了ReStructred Text.

每種狀況下,過濾器都指望字符串形式的格式化標記,並返回表示標記文本的字符串。要激活這些過濾器,僅需將 ‘django.contrib.markup’ 添加到 INSTALLED_APPS 設置中。 一旦完成了該項工做,在模板中經過 {% load markup %} 就能使用這些過濾器。

相關文章
相關標籤/搜索