• Django开发——集成的子框架django.contrib


    Django开发——集成的子框架django.contrib

    Django标准库

    Django的标准库存放在django.contrib包中。每个子包都是一个独立的附加包,这些子包一般都是相互独立的,不过有些子包需要依赖其他子包。
    django.contrib开发包共有的特性是:就算你将整个django.contrib开发包删除,你依然可以使用Django的基础功能而不会遇到任何问题。
    django.contrib由以下开发包组成:

    • 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扩展。

    如何使用多站点框架
    多站点框架:

    • 位于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添加一个多对多字段即可:

    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模型。

    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视图中使用多站点框架,可以让视图根据用站点不同而完成不同的工作。

    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()方法。

    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.
    
    ‐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拥有各子不同的模板目录,可以将工作轻松地转交给模板系统。

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

  • 相关阅读:
    自制游戏Zombie代码
    HNOI2020总结
    20200615题解:继续扮演
    20200611题解:树网的核
    历次考试总结
    寒假总结和省选大体规划
    每日总结
    有一种感动叫ACM(记WJMZBMR在成都赛区开幕式上的讲话)
    递推求欧拉函数的最简单的详解
    总结一些好用的C++小技巧
  • 原文地址:https://www.cnblogs.com/hanbowen/p/10065504.html
Copyright © 2020-2023  润新知