Django的標準庫存放在django.contrib包中。每一個子包都是一個獨立的附加包,這些子包通常都是相互獨立的,不過有些子包須要依賴其餘子包。
django.contrib開發包共有的特性是:就算你將整個django.contrib開發包刪除,你依然可使用Django的基礎功能而不會遇到任何問題。
django.contrib由如下開發包組成:html
如何使用多站點框架
多站點框架:web
安裝多站點應用要執行如下幾個步驟:數據庫
多個站點的數據重用
要在多各站點間重用數據,僅需在模型中爲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)
在適當的位置使用這個技術,你能夠在多站點中重度使用統一段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) # ...
該視圖方法是可重用的,由於它根據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)
從視圖鉤掛當前站點
在底層,經過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.
從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.
獲取當前域用於呈現
依據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]) # ...
在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]) # ...
若是站點在你的應用中扮演很重要的角色,請考慮在你的模型中使用方便的
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()將返回數據庫中全部的Photo對象,而Photo.on_site.all()僅根據SITE_ID設置返回與當前站點相關聯的Photo對象。
Photo.objects.filter(site=settings.SITE_ID) Photo.on_site.all()
這兩條是等價的。
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')
若是傳入一個不存在的字段名,則會引起異常。
Django的特定部分(即Django超級管理站點和通用視圖)使用在模型中定義的第一個管理器,所以若是但願管理站點可以訪問全部對象,請於定義CurrentSiteManager以前在模型中放入objects=models.Manager().
便是隻用Django來支持單個網站,也應該化一點時間用domain和name來建立站點對象,並將SITE_ID設置指向它的ID。
Django如何使用多站點框架:
儘管一般狀況下老是搭建運行數據庫驅動的Web應用,有時還須要添加一兩張一次性的靜態網頁,例如「關於」或者「隱私策略「頁面等。能夠用像Apache這樣標準的Web服務器來處理這些靜態頁面,但卻會給應用帶來一些額外的複雜性,由於你西須操心怎麼配置Apache,還要設置權限讓整個團隊能夠修改編輯這些文件,並且不能使用Django模板系統來統一這些頁面的風格。
這個問題的解決方案使用位於django.contrib.flatpages開發包中的Django簡單頁面應用程序。該應用讓你可以經過Django管理站點來管理這些一次性的頁面。還可讓你使用Django模板系統指定它們使用哪一個模板。它在後臺使用Django模型,這意味着它把頁面像被的數據同樣保存在數據庫。
簡單頁面以它們的URL和站點爲鍵值,當建立簡單頁面時,你指定與哪一個URL以及和哪一個站點相關聯。
使用簡單頁面
安裝簡單頁面步驟:
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'))
一旦完成建立,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>
使用簡單頁面模板
缺省狀況下,使用模板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>
使用safe模板過濾器容許flatpage.content引入原始HTML而沒必要轉意。
經過將重定向存儲在數據庫中並將其視爲Djangp模型對象,Django重定向框架讓你可以輕鬆管理它們。
使用重定向框架
步驟:
在數據庫中建立一個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/>
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 }}
標記過濾器
包 django.contrib.markup 包含了一些列Django模板過濾器,每個都實現了一中通用的標記語言。
每種狀況下,過濾器都指望字符串形式的格式化標記,並返回表示標記文本的字符串。要激活這些過濾器,僅需將 ‘django.contrib.markup’ 添加到 INSTALLED_APPS 設置中。 一旦完成了該項工做,在模板中經過 {% load markup %} 就能使用這些過濾器。