Python hat viele Vorteile, einer davon ist das „ready-to-use“-Prinzip: Bei der Installation von Python werden eine Vielzahl von Standardsoftwarepaketen gleichzeitig installiert, sodass Sie es sofort nutzen können, ohne es tun zu müssen Laden Sie es selbst herunter. Auch Django folgt diesem Prinzip und beinhaltet ebenfalls eine eigene Standardbibliothek. In diesem Kapitel wird über diese integrierten Unterrahmen gesprochen.
Django-Standardbibliothek
Djangos Standardbibliothek ist im django.contrib-Paket enthalten. Jedes Unterpaket ist ein unabhängiges Paket zusätzlicher Funktionen. Sie sind im Allgemeinen nicht unbedingt miteinander verbunden, aber einige Unterpakete von django.contrib können von anderen Paketen abhängen.
Es gibt keine zwingende Anforderung für die Art der Funktionen in django.contrib. Einige dieser Pakete enthalten Modelle (daher müssen Sie die entsprechenden Tabellen in Ihrer Datenbank installieren), andere bestehen jedoch aus eigenständiger Middleware und Vorlagen-Tags.
Das gemeinsame Merkmal des django.contrib-Entwicklungspakets ist: Auch wenn Sie das gesamte django.contrib-Entwicklungspaket löschen, können Sie weiterhin die Grundfunktionen von
verwenden Django ohne Probleme. Wenn Django-Entwickler dem Framework neue Funktionen hinzufügen, werden sie diese Doktrin strikt befolgen, wenn sie entscheiden, ob sie die neue Funktionalität in django.contrib einfügen.
django.contrib besteht aus den folgenden Entwicklungspaketen:
§ admin: automatisiertes Site-Management-Tool. Bitte schauen Sie sich die Django-Administratorseite an
§ auth: Djangos Benutzerauthentifizierungs-Framework. Bitte überprüfen Sie Sitzungen, Benutzer und Registrierungen
§ Kommentare: Eine Kommentaranwendung befindet sich derzeit in intensiver Entwicklung und kann daher zum Zeitpunkt der Veröffentlichung nicht bereitgestellt werden Eine vollständige Beschreibung und weitere Informationen zu dieser Anwendung finden Sie auf der offiziellen Website von Django als eigenständiger Dokumenttyp installiert. Dieses Framework wird in Django hauptsächlich von anderen Anwendungen verwendet und ist in erster Linie für fortgeschrittene Django-Entwickler gedacht. Sie können mehr über dieses Framework erfahren, indem Sie den Quellcode lesen. Der Quellcode befindet sich unter django/contrib/contenttypes/.
§ csrf: Dieses Modul wird zur Vorbeugung verwendet Cross-Site Request Forgery (CSRF) Siehe den späteren Abschnitt mit dem Titel „CSRF-Verteidigung“.
§ Flatpages: Ein Modul, das einzelne HTML-Inhalte in einer Datenbank verwaltet, siehe Abschnitt „Flatpages“ unten.
§ humanisieren: Eine Reihe von Django
Modulfiltern, die zur Verbesserung der Humanisierung von Daten verwendet werden.
§-Markup: Eine Reihe von Django
§ Weiterleitungen: Ein Framework zur Verwaltung von Weiterleitungen.
§ Sitzungen: Djangos Sitzungs-Framework, siehe Sitzungen, Benutzer und Registrierung.
§ Sitemaps: Ein Framework zum Generieren von XML-
-Dateien für Sitemaps. Siehe Django, das Nicht-HTML-Inhalte ausgibt.
§ Websites: Ein Framework, mit dem Sie mehrere Websites innerhalb derselben Datenbank und Django-Installation verwalten können.
§ Syndication: Ein Framework zum Generieren von Syndication-Feeds mithilfe von RSS
und Atom. Siehe Django, das Nicht-HTML-Inhalte ausgibt.
Im Folgenden in diesem Kapitel werden die Inhalte des django.contrib-Entwicklungspakets detailliert beschrieben, die zuvor noch nicht eingeführt wurden.
Mehrere Websites
Djangos Multisite-System ist ein universelles Framework, das es Ihnen ermöglicht, mehrere Websites unter einer Datenbank zu betreiben und das gleiche Django-Projekt. Dies ist ein abstraktes Konzept, das etwas schwer zu verstehen sein kann. Beginnen wir also mit ein paar praktischen Szenarien, in denen es nützlich sein kann.
Szenario 1: Daten für mehrere Standorte wiederverwenden
Wie wir in Kapitel 1 sagten, werden die mit Django erstellten Websites LJWorld.com und Lawrance.com
Lawrence.com auf lokale Unterhaltung konzentriert. Manchmal muss ein Redakteur jedoch einen Artikel auf zwei Websites veröffentlichen.
Eine Sackgassenlösung für dieses Problem könnte darin bestehen, für jede Site eine andere Datenbank zu verwenden und dann den Site-Betreuer zu bitten, denselben Artikel zweimal zu veröffentlichen: einmal für LJWorld .com und ein anderes Mal Lawrence.com. Dies ist jedoch für Site-Administratoren ineffizient und das Speichern mehrerer Kopien desselben Artikels in der Datenbank ist überflüssig.
Eine bessere Lösung? Die beiden Websites verwenden dieselbe Artikeldatenbank und verknüpfen jeden Artikel mithilfe einer Viele-zu-Viele-Beziehung mit einer oder mehreren Websites. Das Django-Site-Framework stellt eine Datenbank bereit, die aufzeichnet, welche Artikel zugeordnet werden können. Es handelt sich um einen Hook, der Daten einer oder mehreren Websites zuordnet.
Szenario 2: Speichern Sie den Namen/die Domain Ihrer Website an einem eindeutigen Ort
LJWorld.com und Lawrence .com verfügt über eine E-Mail-Erinnerungsfunktion, die es den Lesern ermöglicht, nach der Registrierung sofort Benachrichtigungen über Neuigkeiten zu erhalten. Dies ist ein perfekter Mechanismus: Ein Leser sendet ein Registrierungsformular und erhält sofort eine E-Mail mit dem Titel „Vielen Dank für Ihre Anmeldung“.
Es ist offensichtlich ineffizient und überflüssig, den Code dieses Registrierungsprozesses zweimal zu implementieren, sodass die beiden Websites im Hintergrund denselben Code verwenden. Die Benachrichtigung, in der Sie sich für Ihre Anmeldung bedanken, muss jedoch auf beiden Websites unterschiedlich sein. Mithilfe des Site-Objekts können wir die Dankesbenachrichtigung extrahieren, indem wir den Namen der aktuellen Site (z. B. „LJWorld.com“) und die Domäne (z. B. „www.ljworld.com“) verwenden.
Djangos Multisite-Framework bietet Ihnen einen Ort zum Speichern des Namens und der Domäne jeder Site in Ihrem Django-Projekt, was bedeutet, dass Sie sie auf die gleiche Weise wie diese Werte wiederverwenden können.
So verwenden Sie das Multi-Site-Framework
Das Multi-Site-Framework ist weniger ein Framework als vielmehr Es handelt sich um eine Reihe von Konventionen. Alles basiert auf zwei einfachen Konzepten:
§ Das Site-Modell in django.contrib.sites hat zwei Felder: Domain und Name.
§ Die SITE_ID-Einstellung gibt die Datenbank-ID des Site-Objekts an, das einer bestimmten Konfigurationsdatei zugeordnet ist.
Wie Sie diese beiden Konzepte verwenden, bleibt Ihnen überlassen, aber Django erledigt dies automatisch mit ein paar einfachen Konventionen.
Um eine Multi-Site-Anwendung zu installieren, führen Sie die folgenden Schritte aus:
1. Ändern Sie 'django.contrib .sites 'Zu INSTALLED_APPS hinzufügen.
2. Führen Sie den Befehl manage.py syncdb aus, um die Tabelle django_site in der Datenbank zu installieren.
3. Fügen Sie ein oder mehrere
„Site“-Objekte über das Django-Verwaltungs-Backend oder über die Python-API hinzu. Erstellen Sie ein Site-Objekt für jede Site (oder Domäne), die vom Django
-Projekt unterstützt wird.
4. Definieren Sie eine SITE_ID-Variable in jeder Einstellungsdatei. Der Wert dieser Variablen sollte die Datenbank-
ID des Site-Objekts der Site sein, die von der Konfigurationsdatei unterstützt wird.
Funktionen des Multi-Site-Frameworks
In den folgenden Abschnitten werden verschiedene Dinge beschrieben, die mit dem Multi erreicht werden können -Site-Framework-Arbeit.
Wiederverwendung von Daten über mehrere Standorte hinweg
Wie in Szenario 1 erläutert, Datenwiederverwendung über mehrere Standorte hinweg. Zur Wiederverwendung von Daten zwischen Für Websites müssen Sie lediglich ein Viele-zu-Viele-Feld für Website im Modell hinzufügen, zum Beispiel:
from django.db import models from django.contrib.sites.models import Site class Article(models.Model): headline = models.CharField(maxlength=200) # ... sites = models.ManyToManyField(Site)
Dies ist der grundlegende Schritt zum Durchführen von Artikelzuordnungsvorgängen für mehrere Websites in der Datenbank. Mit dieser Technik können Sie denselben Teil des Django-Ansichtscodes auf mehreren Websites wiederverwenden. Um mit dem Artikelmodellbeispiel fortzufahren, ist hier eine mögliche Artikeldetailansicht:
from django.conf import settings def article_detail(request, article_id): try: a = Article.objects.get(id=article_id, sites__id=settings.SITE_ID) except Article.DoesNotExist: raise Http404
# ...
Diese Ansichtsmethode ist wiederverwendbar, da sie Artikel basierend auf dem durch SITE_ID festgelegten Wert dynamisch überprüft Website.
Zum Beispiel ist in der Einstellungsdatei von LJWorld.com die SITE_ID auf 1 gesetzt, und in der Einstellungsdatei von
Lawrence.com ist die SITE_ID auf 2 gesetzt. Wenn diese Ansicht aufgerufen wird, während LJWorld.coms aktiv ist, wird die Suche auf Artikel beschränkt, deren Site-Liste
LJWorld.com enthält.
Verknüpfen von Inhalten mit einer einzelnen Website
Ähnlich können Sie auch Fremdschlüssel im Viele-zu-Eins-Verfahren verwenden Beziehungen Verknüpfen Sie ein Modell mit dem Site-Modell.
Wenn beispielsweise ein bestimmter Artikel nur auf einer Website erscheinen kann, können Sie das folgende Modell verwenden:
from django.db import models from django.contrib.sites.models import Site class Article(models.Model): headline = models.CharField(maxlength=200) # ... site = models.ForeignKey(Site)
Dies ist dasselbe wie Genauso vorteilhaft wie die im vorherigen Abschnitt vorgestellten.
Aktuelle Site aus der Ansicht einbinden
Unter der Haube, indem Sie das Multisite-Framework in einer Django-Ansicht verwenden , Sie können die Ansicht je nach aufrufender Site unterschiedlich ausführen lassen, zum Beispiel:
from django.conf import settings def my_view(request): if settings.SITE_ID == 3: # Do something. else: # Do something else.
Natürlich ist es hässlich, die Site-ID so fest zu codieren. Eine etwas einfachere Möglichkeit, dies zu erreichen, besteht darin, die aktuelle Site-Domäne anzuzeigen:
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.
Üblicherweise wird der Wert „settings.SITE_ID“ aus dem Site-Objekt abgerufen, sodass der Site-Modellmanager
(Site. Objekte) verfügt über eine get_current()-Methode. Das folgende Beispiel entspricht dem vorherigen:
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.
Beachten Sie, dass
in diesem letzten Beispiel Hier , Sie müssen django.conf.settings nicht importieren.
Holen Sie sich die aktuelle Domäne zum Rendern
Wie in Szenario zwei erläutert, zum Speichern des Site-Namens und des Domänennamens für Bei Verwendung der DRY-Methode (Dont Repeat Yourself) (Speichern des Site-Namens und des Domänennamens an einem Ort) müssen Sie nur auf den Namen und die Domäne des aktuellen Site-Objekts verweisen. Zum Beispiel:
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]) # ...
Weiter mit dem Beispiel LJWorld.com und Lawrence.com
, das wir besprochen haben, bei Lawrence.com
die Betreffzeile der E-Mail lautet „Vielen Dank für Ihre Anmeldung.“ die Erinnerungs-E-Mail von Lawrence.com“ . Bei
LJWorld.com lautet die Betreffzeile der E-Mail „Vielen Dank, dass Sie sich für die Erinnerungs-E-Mail von LJWorld.com angemeldet haben“. Dieses standortbezogene Verhalten gilt auch für Betreffzeilen von E-Mail-Nachrichten.
Eine flexiblere (aber schwerere) Möglichkeit, dies zu tun, ist die Verwendung des Vorlagensystems von Django. Vorausgesetzt, dass Lawrence.com und
LJWorld.com jeweils über unterschiedliche Vorlagenverzeichnisse (TEMPLATE_DIRS) verfügen, können Sie die Arbeit einfach wie folgt in das Vorlagensystem übertragen:
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]) # ...
In diesem Beispiel müssen Sie eine subject.txt- und eine message.txt-Vorlage in den Vorlagenverzeichnissen von LJWorld.com und Lawrence.com erstellen
. Wie bereits erwähnt, bringt dieser Ansatz mehr Flexibilität, aber auch mehr Komplexität mit sich.
Die Verwendung so vieler Site-Objekte wie möglich ist eine gute Möglichkeit, unnötige komplexe und redundante Arbeit zu reduzieren.
Erhalten Sie die vollständige URL der aktuellen Domain
Django 的get_absolute_url()约定对与获取不带域名的对象 URL非常理想,但在某些情形下,你可能想显示某个对象带有http://和域名以及所有部分的完整
URL。要完成此工作,你可以使用多站点框架。下面是个简单的例子:
>>> from django.contrib.sites.models import Site >>> obj = MyModel.objects.get(id=3) >>> obj.get_absolute_url() '/mymodel/objects/3/' >>> Site.objects.get_current().domain 'example.com' >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
'http://example.com/mymodel/objects/3/'
当前站点管理器
如果站点在你的应用中扮演很重要的角色,请考虑在你的模型中使用方便的CurrentSiteManager。这是一个模型管理器(见附录B),它会自动过滤使其只包含与当前站点相关联的对象。
通过显示地将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(maxlength=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。下面的模型中有个叫做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(maxlength=100) pub_date = models.DateField() publish_on = models.ForeignKey(Site) objects = models.Manager() on_site = CurrentSiteManager('publish_on')
如果试图使用CurrentSiteManager并传入一个不存在的字段名, Django将引发一个ValueError异常。
注意事项
即便是已经使用了CurrentSiteManager,你也许还想在模型中拥有一个正常的(非站点相关)的管理器。正如在附录
B 中所解释的,如果你手动定义了一个管理器,那么 Django不会为你创建全自动的objects = models.Manager()管理器。
同样,Django的特定部分——即 Django超级管理站点和通用视图——使用的管理器首先在模型中定义,因此如果希望超级管理站点能够访问所有对象(而不是仅仅站点特有对象),请于定义CurrentSiteManager之前在模型中放入objects
= models.Manager()。
Django如何使用多站点框架
尽管并不是必须的,我们还是强烈建议使用多站点框架,因为 Django在几个地方利用了它。即使只用 Django来支持单个网站,你也应该花一点时间用domain和name来创建站点对象,并将SITE_ID设置指向它的
ID 。
以下讲述的是 Django如何使用多站点框架:
§ 在重定向框架中(见后面的重定向一节),每一个重定向对象都与一个特定站点关联。当 Django搜索重定向的时候,它会考虑当前的SITE_ID。
§ 在注册框架中,每个注释都与特定站点相关。每个注释被张贴时,其site被设置为当前的SITE_ID,而当通过适当的模板标签列出注释时,只有当前站点的注释将会显示。
§ 在 flatpages框架中 (参见后面的
Flatpages一节),每个 flatpage都与特定的站点相关联。创建 flatpage时,你都将指定它的site,而
flatpage中间件在获取 flatpage以显示它的过程中,将查看当前的SITE_ID。
§ 在 syndication框架中(参阅Django输出非HTML内容),title和description的模板自动访问变量{{
site }},它就是代表当前着桨的Site对象。Also, the hook for providing item URLs will use thedomainfrom
the currentSiteobject if you dont specify a fully qualified domain.
§ 在身份验证框架(参见Django会话、用户和注册)中,django.contrib.auth.views.login视图将当前Site名称作为{{
site_name }}传递给模板。
Flatpages - 简单页面
尽管通常情况下总是建造和运行数据库驱动的 Web应用,你还是会需要添加一两张一次性的静态页面,例如“关于”页面,或者“隐私策略”页面等等。可以用像
Apache 这样的标准Web服务器来处理这些静态页面,但却会给应用带来一些额外的复杂性,因为你必须操心怎么配置 Apache,还要设置权限让整个团队可以修改编辑这些文件,而且你还不能使用
Django 模板系统来统一这些页面的风格。
这个问题的解决方案是使用位于django.contrib.flatpages开发包中的 Django简单页面(flatpages)应用程序。该应用让你能够通过
Django超级管理站点来管理这些一次性的页面,还可以让你使用 Django模板系统指定它们使用哪个模板。它在后台使用了 Django模型,也就是说它将页面存放在数据库中,你也可以像对待其他数据一样用标准
Django数据库 API
存取简单页面。
简单页面以它们的 URL和站点为键值。当创建简单页面时,你指定它与哪个URL以及和哪个站点相关联。
使用简单页面
安装平页面应用程序必须按照下面的步骤:
1. 添加'django.contrib.flatpages'到INSTALLED_APPS设置。django.contrib.flatpages依赖于django.contrib.sites,所以确保这两个开发包都包括在``INSTALLED_APPS``设置中。
2. 将'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'添加到MIDDLEWARE_CLASSES设置中。
3. 运行manage.py syncdb命令在数据库中创建必需的两个表。
简单页面应用程序在数据库中创建两个表:django_flatpage和django_flatpage_sites。django_flatpage只是将
URL 映射到到标题和一段文本内容。django_flatpage_sites是一个多对多表,用于关联某个简单页面以及一个或多个站点。
该应用所带来的FlatPage模型在django/contrib/flatpages/models.py进行定义,如下所示:
from django.db import models from django.contrib.sites.models import Site class FlatPage(models.Model): url = models.CharField(maxlength=100) title = models.CharField(maxlength=200) content = models.TextField() enable_comments = models.BooleanField() template_name = models.CharField(maxlength=70, blank=True) registration_required = models.BooleanField() sites = models.ManyToManyField(Site)
让我们逐项看看这些字段的含义:
§ url:该简单页面所处的 URL,不包括域名,但是包含前导斜杠
(例如/about/contact/)。
§ title:简单页面的标题。框架不对它作任何特殊处理。由你通过模板来显示它。
§ content:简单页面的内容 (即HTML
页面)。框架不会对它作任何特别处理。由你负责使用模板来显示。
§ enable_comments:是否允许该简单页面使用注释。框架不对此做任何特别处理。你可在模板中检查该值并根据需要显示注释窗体。
§ template_name:用来解析该简单页面的模板名称。这是一个可选项;如果未指定模板或该模板不存在,系统会退而使用默认模板flatpages/default.html。
§ registration_required:是否注册用户才能查看此简单页面。该设置项集成了 Djangos验证/用户框架。
§ sites:该简单页面放置的站点。该项设置集成了 Django多站点框架,该框架在本章的《多站点》一节中有所阐述。
你可以通过 Django超级管理界面或者 Django数据库 API
来创建平页面。要了解更多内容,请查阅《添加、修改和删除简单页面》一节。
一旦简单页面创建完成,FlatpageFallbackMiddleware将完成(剩下)所有的工作。每当 Django引发
404 错误,作为终极手段,该中间件将根据所请求的 URL检查平页面数据库。确切地说,它将使用所指定的 URL以及SITE_ID设置对应的站点
ID查找一个简单页面。
如果找到一个匹配项,它将载入该简单页面的模板(如果没有指定的话,将使用默认模板flatpages/default.html)。同时,它把一个简单的上下文变量——flatpage(一个简单页面对象)传递给模板。在模板解析过程中,它实际用的是RequestContext。
如果FlatpageFallbackMiddleware没有找到匹配项,该请求继续如常处理。
注意
该中间件仅在发生 404(页面未找到)错误时被激活,而不会在 500(服务器错误)或其他错误响应时被激活。还要注意的是必须考虑MIDDLEWARE_CLASSES的顺序问题。通常,你可以把FlatpageFallbackMiddleware放在列表最后,因为它是一种终极手段。
添加、修改和删除简单页面
可以用两种方式增加、变更或删除简单页面:
通过超级管理界面
如果已经激活了自动的 Django超级管理界面,你将会在超级管理页面的首页看到有个 Flatpages区域。你可以像编辑系统中其它对象那样编辑简单页面。
通过 Python API
前面已经提到,简单页面表现为django/contrib/flatpages/models.py中的标准 Django模型。因此,你可以通过
Django数据库 API
来存取简单页面对象,例如:
>>> from django.contrib.flatpages.models import FlatPage >>> from django.contrib.sites.models import Site >>> fp = FlatPage( ... url='/about/', ... title='About', ... content='<p>About this site...</p>', ... enable_comments=False, ... template_name='', ... registration_required=False, ... ) >>> fp.save() >>> 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目录,并把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 }} </body> </html>
重定向
通过将重定向存储在数据库中并将其视为 Django模型对象,Django
重定向框架让你能够轻松地管理它们。比如说,你可以通过重定向框架告诉Django,把任何指向/music/的请求重定向到/sections/arts/music/。当你需要在站点中移动一些东西时,这项功能就派上用场了——网站开发者应该穷尽一切办法避免出现坏链接。
使用重定向框架
安装重定向应用程序必须遵循以下步骤:
1. 将'django.contrib.redirects'添加到INSTALLED_APPS设置中。
2. 将'django.contrib.redirects.middleware.RedirectFallbackMiddleware'添加到MIDDLEWARE_CLASSES设置中。
3. 运行manage.py syncdb命令将所需的表安装到数据库中。
manage.py syncdb在数据库中创建了一个django_redirect表。这是一个简单的查询表,只有site_id、old_path和new_path三个字段。
你可以通过 Django超级管理界面或者 Django数据库 API
来创建重定向。要了解更多信息,请参阅《增加、变更和删除重定向》一节。
一旦创建了重定向,RedirectFallbackMiddleware类将完成所有的工作。每当 Django应用引发一个
404 错误,作为终极手段,该中间件将为所请求的 URL在重定向数据库中进行查找。确切地说,它将使用给定的old_path以及SITE_ID设置对应的站点
ID查找重定向设置。(查阅前面的《多站点》一节可了解关于SITE_ID和多站点框架的更多细节)然后,它将执行以下两个步骤:
§ 如果找到了匹配项,并且new_path非空,它将重定向到new_path。
§ 如果找到了匹配项,但new_path为空,它将发送一个 410 (Gone) HTTP头信息以及一个空(无内容)响应。
§ 如果未找到匹配项,该请求将如常处理。
该中间件仅为 404错误激活,而不会为 500
错误或其他任何状态码的响应所激活。
注意必须考虑MIDDLEWARE_CLASSES的顺序。通常,你可以将RedirectFallbackMiddleware放置在列表的最后,因为它是一种终极手段。
注意
如果同时使用重定向和简单页面回退中间件,必须考虑先检查其中的哪一个(重定向或简单页面)。我们建议将简单页面放在重定向之前(因此将简单页面中间件放置在重定向中间件之前),但你可能有不同想法。
增加、变更和删除重定向
你可以两种方式增加、变更和删除重定向:
通过超级管理界面
如果已经激活了全自动的 Django超级管理界面,你应该能够在超级管理首页看到重定向区域。可以像编辑系统中其它对象一样编辑重定向。
通过 Python API
django/contrib/redirects/models.py中的一个标准 Django模型代表了重定向。因此,你可以通过 Django数据库
API 来存取重定向对象,例如:
>>> from django.contrib.redirects.models import Redirect >>> from django.contrib.sites.models import Site >>> red = Redirect( ... site=Site.objects.get(id=1), ... old_path='/music/', ... new_path='/sections/arts/music/', ... ) >>> red.save() >>> Redirect.objects.get(old_path='/music/') <Redirect: /music/ ---> /sections/arts/music/>
CSRF 防护
django.contrib.csrf开发包能够防止遭受跨站请求伪造攻击 (CSRF).
CSRF, 又叫进程跳转,是一种网站安全攻击技术。当某个恶意网站在用户未察觉的情况下将其从一个已经通过身份验证的站点诱骗至一个新的 URL时,这种攻击就发生了,因此它可以利用用户已经通过身份验证的状态。开始的时候,要理解这种攻击技术比较困难,因此我们在本节将使用两个例子来说明。
一个简单的 CSRF例子
假定你已经登录到example.com的网页邮件账号。该网页邮件站点上有一个登出按钮指向了 URLexample.com/logout,换句话说,要登出的话,需要做的唯一动作就是访问
URL :example.com/logout。
通过在(恶意)网页上用隐藏一个指向 URLexample.com/logout的
诚然,对你而言登出一个网页邮件站点并不会构成多大的安全破坏,但同样的攻击可能发生在任何信任用户的站点之上,比如在线银行网站或者电子商务网站。
稍微复杂一点的CSRF例子
Im vorherigen Beispiel ist example.com teilweise dafür verantwortlich, da es Statusänderungen (d. h. An- und Abmeldung) über die HTTP-GET-Methode zulässt. Die Situation wäre viel besser, wenn die
HTTPPOST-Methode für Serverstatusänderungen erforderlich wäre. Auch wenn die Verwendung der POST-Methode für Zustandsänderungsvorgänge obligatorisch ist, ist sie dennoch anfällig für CSRF-Angriffe.
Angenommen, example.com hat die Abmeldefunktion aktualisiert. Die Abmeldung der Schaltfläche