好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Django集成的子框架

Python有众多优点,其中之一就是“开机即用”原则:安装Python的同时安装好大量的标准软件包,这样你可以立即使用而不用自己去下载。Django也遵循这个原则,它同样包含了自己的标准库。这一章就来讲这些集成的子框架。

正如在情景一中所解释的,要在多个站点间重用数据,仅需在模型中为Site添加一个多对多字段即可,例如:

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) 

这是在数据库中为多个站点进行文章关联操作的基础步骤。在适当的位置使用该技术,你可以在多个站点中重复使用同一段 Django视图代码。继续Article模型范例,下面是一个可能的article_detail视图:

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 

举例来说,如果某篇文章仅仅能够出现在一个站点上,你可以使用下面这样的模型:

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) 

在底层,通过在 Django视图中使用多站点框架,你可以让视图根据调用站点不同而完成不同的工作,例如:

from django.conf import settings
def my_view(request):
if settings.SITE_ID == 3:
# Do something.
else:
# Do something else. 

当然,像那样对站点 ID进行硬编码是比较难看的。略为简洁的完成方式是查看当前的站点域:

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测试数据':
# Do something
else:
# Do something else. 
from django.contrib.sites.models import Site
def my_view(request):
current_site = Site.objects.get_current()
if current_site.domain == 'foo测试数据':
# Do something
else:
# Do something else. 

正如情景二中所解释的那样,对于储存站名和域名的 DRY (Dont Repeat Yourself)方法(在一个位置储存站名和域名)来说,只需引用当前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])
# ... 

完成这项工作的一种更加灵活(但重量级也更大)的方法是使用 Django的模板系统。假定 Lawrence测试数据和
LJWorld测试数据 各自拥有不同的模板目录(TEMPLATE_DIRS),你可将工作轻松地转交给模板系统,如下所示:

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测试数据', [user_email])
# ... 

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测试数据'
>>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url()) 
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.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') 

该应用所带来的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) 

前面已经提到,简单页面表现为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模板范例:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://HdhCmsTestw3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<title>{{ flatpage.title }}</title>
</head>
<body>
{{ flatpage.content }}
</body>
</html> 

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/> 

{{ object.content|textile }}

要激活这些过滤器,仅需将'django.contrib.markup'添加到INSTALLED_APPS设置中。一旦完成了该项工作,在模板中使用{%
load markup %}就能使用这些过滤器。要想掌握更多信息的话,可阅读django/contrib/markup/templatetags/markup.py.内的源代码。

以上就是Django集成的子框架的内容,更多相关内容请关注PHP中文网(HdhCmsTestgxlcms测试数据)!

查看更多关于Django集成的子框架的详细内容...

  阅读:40次