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 %} 就能使用这些过滤器。