QQ登录 - 设为首页 - 加入收藏 - 网站地图 木易瓶子屋!第一时间了解互联网开发技术新鲜事儿!

亲!来点一下试试嘛。。。

木易瓶子屋每日新鲜技术平台 第一时间了解互联网的那些事儿

第十三章:Django 输出非HTML内容

作者:木易瓶子┆ 分类:python学习┆时间:2015-02-12┆点击: 121次┆tags: 第十三章Django输出非HTML

通常当我们谈到开发网站时,主要谈论的是HTML。 当然,Web远不只有HTML,我们在Web上用多种格式来发布数据: RSS、PDF、图片等。

到目前为止,我们的注意力都是放在常见 HTML 代码生成上,但是在这一章中,我们将会对使用 Django 生成其它格式的内容进行简要介绍。

Django拥有一些便利的内建工具帮助你生成常见的非HTML内容:

  • RSS/Atom 聚合文件

  • 站点地图 (一个XML格式文件,最初由Google开发,用于给搜索引擎提示线索)

我们稍后会逐一研究这些工具,不过首先让我们来了解些基础原理。

基础: 视图和MIME类型

回顾一下第三章,视图函数只是一个以Web请求为参数并返回Web响应的Python函数。 这个响应可以是一个Web页面的HTML内容,或者一个跳转,或者一个404 错误,或者一个XML文档,或者一幅图片,或者映射到任何东西上。

更正式的说,一个Django视图函数 必须

  • 接受一个 HttpRequest 实例作为它的第一个参数

  • 返回一个 HttpResponse 实例

从一个视图返回一个非 HTML 内容的关键是在构造一个 HttpResponse 类时,需要指定 mimetype 参数。 通过改变 MIME 类型,我们可以通知浏览器将要返回的数据是另一种类型。

下面我们以返回一张PNG图片的视图为例。 为了使事情能尽可能的简单,我们只是读入一张存储在磁盘上的图片:

from django.http import HttpResponse

def my_image(request):
    image_data = open("/path/to/my/image.png", "rb").read()
    return HttpResponse(image_data, mimetype="image/png")

就是这么简单。 如果改变 open() 中的图片路径为一张真实图片的路径,那么就可以使用这个十分简单的视图来提供一张图片,并且浏览器可以正确显示它。

另外我们必须了解的是HttpResponse对象实现了Python标准的文件应用程序接口(API)。 这就是说你可以在Python(或第三方库)任何用到文件的地方使用”HttpResponse”实例。

下面将用 Django 生成 CSV 文件为例,说明它的工作原理。

生成 CSV 文件

CSV 是一种简单的数据格式,通常为电子表格软件所使用。 它主要是由一系列的表格行组成,每行中单元格之间使用逗号(CSV 是 逗号分隔数值(comma-separated values) 的缩写)隔开。例如,下面是CSV格式的“不守规矩”的飞机乘客表。

Year,Unruly Airline Passengers
1995,146
1996,184
1997,235
1998,200
1999,226
2000,251
2001,299
2002,273
2003,281
2004,304
2005,203
2006,134
2007,147

备注

前面的列表包含真实数据。 这些数据来自美国 联邦航空管理局。

CSV格式尽管看起来简单,却是全球通用的。 但是不同的软件会生成和使用不同的 CSV 的变种,在使用上会有一些不便。 幸运的是, Python 使用的是标准 CSV 库, csv ,所以它更通用。

因为 csv 模块操作的是类似文件的对象,所以可以使用 HttpResponse 替换:

import csv
from django.http import HttpResponse

# Number of unruly passengers each year 1995 - 2005. In a real application
# this would likely come from a database or some other back-end data store.
UNRULY_PASSENGERS = [146,184,235,200,226,251,299,273,281,304,203]

def unruly_passengers_csv(request):
    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(mimetype='text/csv')
    response['Content-Disposition'] = 'attachment; filename=unruly.csv'

    # Create the CSV writer using the HttpResponse as the "file."
    writer = csv.writer(response)
    writer.writerow(['Year', 'Unruly Airline Passengers'])
    for (year, num) in zip(range(1995, 2006), UNRULY_PASSENGERS):
        writer.writerow([year, num])

    return response

代码和注释可以说是很清楚,但还有一些事情需要特别注意:

响应返回的是 text/csv MIME类型(而非默认的 text/html )。这会告诉浏览器,返回的文档是CSV文件。

响应会有一个附加的 Content-Disposition 头部,它包含有CSV文件的文件名。 这个头部(或者说,附加部分)会指示浏览器弹出对话框询问文件存放的位置(而不仅仅是显示)。 这个文件名是任意的。 它会显示在浏览器的另存为对话框中。

要在HttpResponse指定头部信息,只需把HttpResponse当做字典使用就可以了。

与创建CSV的应用程序界面(API)挂接是很容易的: 只需将 response 作为第一个变量传递给 csv.writer。 csv.writer 函数需要一个文件类的对象, HttpResponse 正好能达成这个目的。

调用 writer.writerow ,并且传递给它一个类似 list 或者 tuple 的可迭代对象,就可以在 CSV 文件中写入一行。

CSV 模块考虑到了引用的问题,所以您不用担心逸出字符串中引号和逗号。 只要把信息传递给 writerow(),它会处理好所有的事情。

在任何需要返回非 HTML 内容的时候,都需要经过以下几步: 创建一个 HttpResponse 响应对象(需要指定特殊的 MIME 类型),它它传给需要处理文件的函数,然后返回这个响应对象。

下面是一些其它的例子。

生成 PDF 文件

便携文档格式 (PDF) 是由 Adobe 开发的格式,主要用于呈现可打印的文档,其中包含有 pixel-perfect 格式,嵌入字体以及2D矢量图像。 You can think of a PDF document as the digital equivalent of a printed document; indeed, PDFs are often used in distributing documents for the purpose of printing them.

可以方便的使用 Python 和 Django 生成 PDF 文档需要归功于一个出色的开源库, ReportLab (http://www.reportlab.org/rl_toolkit.html) 。动态生成 PDF 文件的好处是在不同的情况下,如不同的用户或者不同的内容,可以按需生成不同的 PDF 文件。 The advantage of generating PDF files dynamically is that you can create customized PDFs for different purposes say, for different users or different pieces of content.

下面的例子是使用 Django 和 ReportLab 在 KUSports.com 上生成个性化的可打印的 NCAA 赛程表 (tournament brackets) 。

安装 ReportLab

在生成 PDF 文件之前,需要安装 ReportLab 库。这通常是个很简单的过程: Its usually simple: just download and install the library from http://www.reportlab.org/downloads.html.

Note

如果使用的是一些新的 Linux 发行版,则在安装前可以先检查包管理软件。 多数软件包仓库中都加入了 ReportLab 。

比如,如果使用(杰出的) Ubuntu 发行版,只需要简单的 apt-get install python-reportlab 一行命令即可完成安装。

使用手册(原始的只有 PDF 格式)可以从 http://www.reportlab.org/rsrc/userguide.pdf 下载,其中包含有一些其它的安装指南。

在 Python 交互环境中导入这个软件包以检查安装是否成功。

>>> import reportlab

如果刚才那条命令没有出现任何错误,则表明安装成功。

编写视图

和 CSV 类似,由 Django 动态生成 PDF 文件很简单,因为 ReportLab API 同样可以使用类似文件对象。

下面是一个 Hello World 的示例:

from reportlab.pdfgen import canvas
from django.http import HttpResponse

def hello_pdf(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=hello.pdf'

    # Create the PDF object, using the response object as its "file."
    p = canvas.Canvas(response)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly, and we're done.
    p.showPage()
    p.save()
    return response

需要注意以下几点:

  • 这里我们使用的 MIME 类型是 application/pdf 。这会告诉浏览器这个文档是一个 PDF 文档,而不是 HTML 文档。 如果忽略了这个参数,浏览器可能会把这个文件看成 HTML 文档,这会使浏览器的窗口中出现很奇怪的文字。 If you leave off this information, browsers will probably interpret the response as HTML, which will result in scary gobbledygook in the browser window.

  • 使用 ReportLab 的 API 很简单: 只需要将 response 对象作为 canvas.Canvas 的第一个参数传入。

  • 所有后续的 PDF 生成方法需要由 PDF 对象调用(在本例中是 p ),而不是 response 对象。

  • 最后需要对 PDF 文件调用 showPage() 和 save() 方法(否则你会得到一个损坏的 PDF 文件)。

复杂的 PDF 文件

如果您在创建一个复杂的 PDF 文档(或者任何较大的数据块),请使用 cStringIO 库存放临时生成的 PDF 文件。 cStringIO 提供了一个用 C 编写的类似文件对象的接口,从而可以使系统的效率最高。

下面是使用 cStringIO 重写的 Hello World 例子:

from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def hello_pdf(request):
    # Create the HttpResponse object with the appropriate PDF headers.
    response = HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=hello.pdf'

    temp = StringIO()

    # Create the PDF object, using the StringIO object as its "file."
    p = canvas.Canvas(temp)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly.
    p.showPage()
    p.save()

    # Get the value of the StringIO buffer and write it to the response.
    response.write(temp.getvalue())
    return response

其它的可能性

使用 Python 可以生成许多其它类型的内容,下面介绍的是一些其它的想法和一些可以用以实现它们的库。 Here are a few more ideas and some pointers to libraries you could use to implement them:

ZIP 文件 :Python 标准库中包含有 zipfile 模块,它可以读和写压缩的 ZIP 文件。 它可以用于按需生成一些文件的压缩包,或者在需要时压缩大的文档。 如果是 TAR 文件则可以使用标准库 tarfile 模块。

动态图片 : Python 图片处理库 (PIL; http://www.pythonware.com/products/pil/) 是极好的生成图片(PNG, JPEG, GIF 以及其它许多格式)的工具。 它可以用于自动为图片生成缩略图,将多张图片压缩到单独的框架中,或者是做基于 Web 的图片处理。

图表 : Python 有许多出色并且强大的图表库用以绘制图表,按需地图,表格等。 我们不可能将它们全部列出,所以下面列出的是个中的翘楚。

总之,所有可以写文件的库都可以与 Django 同时使用。 The possibilities are immense.

我们已经了解了生成“非HTML”内容的基本知识,让我们进一步总结一下。 Django拥有很多用以生成各类“非HTML”内容的内置工具。

内容聚合器应用框架

Django带来了一个高级的聚合生成框架,它使得创建RSS和Atom feeds变得非常容易。

什么是RSS? 什么是Atom?

RSS和Atom都是基于XML的格式,你可以用它来提供有关你站点内容的自动更新的feed。 了解更多关于RSS的可以访问 http://www.whatisrss.com/, 更多Atom的信息可以访问 http://www.atomenabled.org/.

想创建一个联合供稿的源(syndication feed),所需要做的只是写一个简短的python类。 你可以创建任意多的源(feed)。

高级feed生成框架是一个默认绑定到/feeds/的视图,Django使用URL的其它部分(在/feeds/之后的任何东西)来决定输出 哪个feed Django uses the remainder of the URL (everything after /feeds/ ) to determine which feed to return.

要创建一个 sitemap,你只需要写一个 Sitemap 类然后配置你的URLconf指向它。

初始化

为了在您的Django站点中激活syndication feeds, 添加如下的 URLconf:

(r'^feeds/(?P.*)/$', 'django.contrib.syndication.views.feed',
    {'feed_dict': feeds}
),

这一行告诉Django使用RSS框架处理所有的以 "feeds/" 开头的URL. ( 你可以修改 "feeds/" 前缀以满足您自己的要求. )

URLConf里有一行参数: {'feed_dict': feeds},这个参数可以把对应URL需要发布的feed内容传递给 syndication framework

特别的,feed_dict应该是一个映射feed的slug(简短URL标签)到它的Feed类的字典 你可以在URL配置本身里定义feed_dict,这里是一个完整的例子 You can define the feed_dict in the URLconf itself. Here’s a full example URLconf:

from django.conf.urls.defaults import *
from mysite.feeds import LatestEntries, LatestEntriesByCategory

feeds = {
    'latest': LatestEntries,
    'categories': LatestEntriesByCategory,
}

urlpatterns = patterns('',
    # ...
    (r'^feeds/(?P.*)/$', 'django.contrib.syndication.views.feed',
        {'feed_dict': feeds}),
    # ...
)

前面的例子注册了两个feed:

  • LatestEntries``表示的内容将对应到``feeds/latest/ .

  • LatestEntriesByCategory``的内容将对应到 ``feeds/categories/ .

以上的设定完成之后,接下来需要自己定义 Feed 类

一个 Feed 类是一个简单的python类,用来表示一个syndication feed. 一个feed可能是简单的 (例如一个站点新闻feed,或者最基本的,显示一个blog的最新条目),也可能更加复杂(例如一个显示blog某一类别下所有条目的feed。 这里类别 category 是个变量).

Feed类必须继承django.contrib.syndication.feeds.Feed,它们可以在你的代码树的任何位置

一个简单的Feed

This simple example describes a feed of the latest five blog entries for a given blog:

from django.contrib.syndication.feeds import Feed
from mysite.blog.models import Entry

class LatestEntries(Feed):
    title = "My Blog"
    link = "/archive/"
    description = "The latest news about stuff."

    def items(self):
        return Entry.objects.order_by('-pub_date')[:5]

要注意的重要的事情如下所示:

  • 子类 django.contrib.syndication.feeds.Feed .

  • title , link , 和 description 对应一个标准 RSS 里的  </tt> , <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><link /></tt> , 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><description></tt> 标签.</p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn105" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn105" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> 是一个方法,返回一个用以包含在包含在feed的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><item></tt> 元素里的 list 虽然例子里用Djangos database API返回的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">NewsItem</tt> 对象, <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> 不一定必须返回 model的实例 Although this example returns <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Entry</tt> objects using Django’s database API, <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> doesn’t have to return model instances.</p></li></ul><p class="cn" id="cn106" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">还有一个步骤,在一个RSS feed里,每个(item)有一个(title),(link)和(description),我们需要告诉框架 把数据放到这些元素中 In an RSS feed, each <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><item></tt> has a <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><title></tt> , <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><link /></tt> , and <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><description></tt> . We need to tell the framework what data to put into those elements.</p><blockquote style="margin:1em 0px;padding:0px 1em;line-height:1.2em;font-family:'Trebuchet MS', sans-serif;border-left-width:2px;border-left-style:solid;border-left-color:#94DA3A;color:#333333 !important;"><p class="cn" id="cn107" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">如果要指定 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><title></tt> 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><description></tt> ,可以建立一个Django模板(见Chapter 4)名字叫<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">feeds/latest_title.html</tt> 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">feeds/latest_description.html</tt> ,后者是URLConf里为对应feed指定的<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">slug</tt> 。注意 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">.html</tt> 后缀是必须的。 Note that the <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">.html</tt> extension is required.</p><p class="cn" id="cn108" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">RSS系统模板渲染每一个条目,需要给传递2个参数给模板上下文变量:</p><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn109" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn109" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">obj</tt> : 当前对象 ( 返回到 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> 任意对象之一 )。</p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn110" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn110" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">site</tt> : 一个表示当前站点的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.models.core.sites.Site</tt> 对象。 这对于 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">{{ site.domain }}</tt> 或者<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">{{ site.name }}</tt> 很有用。</p></li></ul><p class="cn" id="cn111" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">如果你在创建模板的时候,没有指明标题或者描述信息,框架会默认使用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">"{{ obj }}"</tt> ,对象的字符串表示。 (For model objects, this will be the <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">__unicode__()</tt> method.</p><p class="cn" id="cn112" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">你也可以通过修改 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 类中的两个属性 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">title_template</tt> 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">description_template</tt> 来改变这两个模板的名字。</p><p class="cn" id="cn113" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">你有两种方法来指定 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><link /></tt> 的内容。 Django 首先执行 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> 中每一项的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">get_absolute_url()</tt> 方法。 如果该方法不存在,就会尝试执行 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 类中的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">item_link()</tt> 方法,并将自身作为 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">item</tt> 参数传递进去。</p><p class="cn" id="cn114" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">get_absolute_url()</tt> 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">item_link()</tt> 都应该以Python字符串形式返回URL。</p><p class="cn" id="cn115" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">对于前面提到的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">LatestEntries</tt> 例子,我们可以实现一个简单的feed模板。 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">latest_title.html</tt> 包括:</p></blockquote> <pre class="cn literal-block" id="cn117" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">{{ obj.title }} </pre> <blockquote style="margin:1em 0px;padding:0px 1em;line-height:1.2em;font-family:'Trebuchet MS', sans-serif;border-left-width:2px;border-left-style:solid;border-left-color:#94DA3A;color:#333333 !important;"><p class="cn" id="cn118" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">并且 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">latest_description.html</tt> 包含:</p></blockquote> <pre class="cn literal-block" id="cn120" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">{{ obj.description }} </pre> <blockquote style="margin:1em 0px;padding:0px 1em;line-height:1.2em;font-family:'Trebuchet MS', sans-serif;border-left-width:2px;border-left-style:solid;border-left-color:#94DA3A;color:#333333 !important;"><p class="cn" id="cn121" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">这真是 <em>太</em> 简单了!</p></blockquote></div><div class="section" id="id6" style="margin:0px;padding:0px;"><span id="cn122"></span> <h3 class="cn" id="cn122" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">一个更复杂的Feed</h3><p class="cn" id="cn123" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">框架通过参数支持更加复杂的feeds。</p><p class="cn" id="cn124" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">For example, say your blog offers an RSS feed for every distinct tag you’ve used to categorize your entries. 如果为每一个单独的区域建立一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 类就显得很不明智。</p><p class="cn" id="cn125" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">取而代之的方法是,使用聚合框架来产生一个通用的源,使其可以根据feeds URL返回相应的信息。</p><p class="cn" id="cn126" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">Your tag-specific feeds could use URLs like this:</p><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn127" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn127" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">http://example.com/feeds/tags/python/</tt> : Returns recent entries tagged with python</p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn128" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn128" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">http://example.com/feeds/tags/cats/</tt> : Returns recent entries tagged with cats</p></li></ul><p class="cn" id="cn129" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">固定的那一部分是 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">"beats"</tt> (区域)。</p><p class="cn" id="cn130" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">举个例子会澄清一切。 下面是每个地区特定的feeds:</p> <pre class="cn literal-block" id="cn132" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from django.core.exceptions import ObjectDoesNotExist from mysite.blog.models import Entry, Tag class TagFeed(Feed): def get_object(self, bits): # In case of "/feeds/tags/cats/dogs/mice/", or other such # clutter, check that bits has only one member. if len(bits) != 1: raise ObjectDoesNotExist return Tag.objects.get(tag=bits[0]) def title(self, obj): return "My Blog: Entries tagged with %s" % obj.tag def link(self, obj): return obj.get_absolute_url() def description(self, obj): return "Entries tagged with %s" % obj.tag def items(self, obj): entries = Entry.objects.filter(tags__id__exact=obj.id) return entries.order_by('-pub_date')[:30] </pre> <p class="cn" id="cn133" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">以下是RSS框架的基本算法,我们假设通过URL <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">/rss/beats/0613/</tt> 来访问这个类:</p><blockquote style="margin:1em 0px;padding:0px 1em;line-height:1.2em;font-family:'Trebuchet MS', sans-serif;border-left-width:2px;border-left-style:solid;border-left-color:#94DA3A;color:#333333 !important;"><p class="cn" id="cn134" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">框架获得了URL <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">/rss/beats/0613/</tt> 并且注意到URL中的slug部分后面含有更多的信息。 它将斜杠(<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">"/"</tt> )作为分隔符,把剩余的字符串分割开作为参数,调用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 类的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">get_object()</tt> 方法。</p><p class="cn" id="cn135" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">在这个例子中,添加的信息是 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">['0613']</tt> 。对于 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">/rss/beats/0613/foo/bar/</tt> 的一个URL请求, 这些信息就是 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">['0613', 'foo', 'bar']</tt> 。</p><p class="cn" id="cn136" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">get_object()</tt> 就根据给定的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">bits</tt> 值来返回区域信息。</p><p class="cn" id="cn137" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">In this case, it uses the Django database API to retrieve the <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Tag</tt> . Note that <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">get_object()</tt> should raise<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.core.exceptions.ObjectDoesNotExist</tt> if given invalid parameters. 在 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Beat.objects.get()</tt> 调用中也没有出现 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">try</tt> /<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">except</tt> 代码块。 函数在出错时抛出 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Beat.DoesNotExist</tt> 异常,而 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Beat.DoesNotExist</tt>是 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">ObjectDoesNotExist</tt> 异常的一个子类型。</p><p class="cn" id="cn138" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">为产生 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><title></tt> , <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><link /></tt> , 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><description></tt> 的feeds, Django使用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">title()</tt> , <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">link()</tt> , 和<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">description()</tt> 方法。 在上面的例子中,它们都是简单的字符串类型的类属性,而这个例子表明,它们既可以是字符串, <em>也可以是</em> 方法。 对于每一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">title</tt> , <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">link</tt> 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">description</tt> 的组合,Django使用以下的算法:</p><ol class="arabic simple" style="margin:0px;padding:0px 0px 0px 30px;list-style-position:initial;list-style-image:initial;"><li class="cn" id="cn139" style="margin:0px 0px 0.4em;padding:0px;position:relative;"><p class="first cn" id="cn139" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">试图调用一个函数,并且以 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">get_object()</tt> 返回的对象作为参数传递给 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">obj</tt> 参数。</p></li></ol><ol class="arabic simple" start="2" style="margin:0px;padding:0px 0px 0px 30px;list-style-position:initial;list-style-image:initial;"><li class="cn" id="cn140" style="margin:0px 0px 0.4em;padding:0px;position:relative;"><p class="first cn" id="cn140" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">如果没有成功,则不带参数调用一个方法。</p></li></ol><ol class="arabic simple" start="3" style="margin:0px;padding:0px 0px 0px 30px;list-style-position:initial;list-style-image:initial;"><li class="cn" id="cn141" style="margin:0px 0px 0.4em;padding:0px;position:relative;"><p class="first cn" id="cn141" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">还不成功,则使用类属性。</p></li></ol><p class="cn" id="cn142" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">最后,值得注意的是,这个例子中的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> 使用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">obj</tt> 参数。 对于 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items</tt> 的算法就如同上面第一步所描述的那样,首先尝试 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items(obj)</tt> , 然后是 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> ,最后是 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items</tt> 类属性(必须是一个列表)。</p></blockquote><p class="cn" id="cn143" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 类所有方法和属性的完整文档,请参考官方的Django文档 (<a class="reference external" tppabs="http://www.djangoproject.com/documentation/0.96/syndication_feeds/" style="color:#AB5603;">http://www.djangoproject.com/documentation/0.96/syndication_feeds/</a>) 。</p></div><div class="section" id="id7" style="margin:0px;padding:0px;"><span id="cn144"></span> <h3 class="cn" id="cn144" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">指定Feed的类型</h3><p class="cn" id="cn145" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">默认情况下, 聚合框架生成RSS 2.0. 要改变这样的情况, 在 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 类中添加一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">feed_type</tt> 属性. To change that, add a <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">feed_type</tt> attribute to your <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> class:</p> <pre class="cn literal-block" id="cn147" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from django.utils.feedgenerator import Atom1Feed class MyFeed(Feed): feed_type = Atom1Feed </pre> <p class="cn" id="cn148" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">注意你把 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">feed_type</tt> 赋值成一个类对象,而不是类实例。 目前合法的Feed类型如表11-1所示。</p><table class="cn docutils" id="cn149" style="border-spacing:0px;color:#000000;margin-bottom:1em;width:682px;position:relative;"><caption style="font-weight:bold;font-size:1em;margin-top:0.5em;margin-bottom:0.5em;margin-left:2px;">表 11-1. Feed 类型</caption><colgroup><col width="73%" /><col width="27%" /></colgroup> <thead valign="bottom"><tr><th class="head" style="margin:0px;padding:4px 2px;border-bottom-width:2px;border-bottom-style:solid;border-bottom-color:#DFDFDF;white-space:nowrap;">Feed 类</th><th class="head" style="margin:0px;padding:4px 2px;border-bottom-width:2px;border-bottom-style:solid;border-bottom-color:#DFDFDF;white-space:nowrap;">类型</th></tr></thead><tbody valign="top"><tr><td style="margin:0px;padding:4px 2px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#DFDFDF;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;background:none;">django.utils.feedgenerator.Rss201rev2Feed</tt> </td><td style="margin:0px;padding:4px 2px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#DFDFDF;">RSS 2.01 (default)</td></tr><tr><td style="margin:0px;padding:4px 2px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#DFDFDF;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;background:none;">django.utils.feedgenerator.RssUserland091Feed</tt> </td><td style="margin:0px;padding:4px 2px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#DFDFDF;">RSS 0.91</td></tr><tr><td style="margin:0px;padding:4px 2px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#DFDFDF;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;background:none;">django.utils.feedgenerator.Atom1Feed</tt> </td><td style="margin:0px;padding:4px 2px;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:#DFDFDF;">Atom 1.0</td></tr></tbody></table></div><div class="section" id="id8" style="margin:0px;padding:0px;"><span id="cn150"></span> <h3 class="cn" id="cn150" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">闭包</h3><p class="cn" id="cn151" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">为了指定闭包(例如,与feed项比方说MP3 feeds相关联的媒体资源信息),使用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">item_enclosure_url</tt> ,<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">item_enclosure_length</tt> , 以及 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">item_enclosure_mime_type</tt> ,比如</p> <pre class="cn literal-block" id="cn153" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from myproject.models import Song class MyFeedWithEnclosures(Feed): title = "Example feed with enclosures" link = "/feeds/example-with-enclosures/" def items(self): return Song.objects.all()[:30] def item_enclosure_url(self, item): return item.song_url def item_enclosure_length(self, item): return item.song_length item_enclosure_mime_type = "audio/mpeg" </pre> <p class="cn" id="cn154" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">当然,你首先要创建一个包含有 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">song_url</tt> 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">song_length</tt> (比如按照字节计算的长度)域的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Song</tt> 对象。</p></div><div class="section" id="id9" style="margin:0px;padding:0px;"><span id="cn155"></span> <h3 class="cn" id="cn155" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">语言</h3><p class="cn" id="cn156" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">聚合框架自动创建的Feed包含适当的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><language></tt> 标签(RSS 2.0) 或 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">xml:lang</tt> 属性(Atom). 他直接来自于您的<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">LANGUAGE_CODE</tt> 设置. This comes directly from your <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">LANGUAGE_CODE</tt> setting.</p></div><div class="section" id="urls" style="margin:0px;padding:0px;"><span id="cn157"></span> <h3 class="cn" id="cn157" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">URLs</h3><p class="cn" id="cn158" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">link</tt> 方法/属性可以以绝对URL的形式(例如, <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">"/blog/"</tt> )或者指定协议和域名的URL的形式返回(例如<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">"http://www.example.com/blog/"</tt> )。如果 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">link</tt> 没有返回域名,聚合框架会根据 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">SITE_ID</tt> 设置,自动的插入当前站点的域信息。 (See Chapter 16 for more on <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">SITE_ID</tt> and the sites framework.)</p><p class="cn" id="cn159" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">Atom feeds需要 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;"><link rel="self" /></tt> 指明feeds现在的位置。 The syndication framework populates this automatically.</p></div><div class="section" id="atom-and-rss" style="margin:0px;padding:0px;"><span id="cn160"></span> <h3 class="cn" id="cn160" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">同时发布Atom and RSS</h3><p class="cn" id="cn161" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">一些开发人员想 <em>同时</em> 支持Atom和RSS。 这在Django中很容易实现: 只需创建一个你的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">feed</tt> 类的子类,然后修改 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">feed_type</tt> ,并且更新URLconf内容。 下面是一个完整的例子: Here’s a full example:</p> <pre class="cn literal-block" id="cn163" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from django.contrib.syndication.feeds import Feed from django.utils.feedgenerator import Atom1Feed from mysite.blog.models import Entry class RssLatestEntries(Feed): title = "My Blog" link = "/archive/" description = "The latest news about stuff." def items(self): return Entry.objects.order_by('-pub_date')[:5] class AtomLatestEntries(RssLatestEntries): feed_type = Atom1Feed </pre> <p class="cn" id="cn164" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">这是与之相对应那个的URLconf:</p> <pre class="cn literal-block" id="cn166" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from django.conf.urls.defaults import * from myproject.feeds import RssLatestEntries, AtomLatestEntries feeds = { 'rss': RssLatestEntries, 'atom': AtomLatestEntries, } urlpatterns = patterns('', # ... (r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', {'feed_dict': feeds}), # ... ) </pre> </div></div><div class="section" id="sitemap" style="margin:0px;padding:0px;font-family:'Microsoft YaHei', 'Lucida Grande', Verdana;white-space:normal;background-color:#FFFFFF;"><span id="cn167"></span> <h2 class="cn" id="cn167" style="margin:1.4em 0px 0px;padding:0px;font-size:17px;font-weight:normal;color:#487858;position:relative;">Sitemap 框架</h2><p class="cn" id="cn168" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><em>sitemap</em> 是你服务器上的一个XML文件,它告诉搜索引擎你的页面的更新频率和某些页面相对于其它页面的重要性。 这个信息会帮助搜索引擎索引你的网站。</p><p class="cn" id="cn169" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">例如,这是 Django 网站(<a class="reference external" tppabs="http://www.djangoproject.com/sitemap.xml" style="color:#AB5603;">http://www.djangoproject.com/sitemap.xml</a>)sitemap的一部分:</p> <pre class="cn literal-block" id="cn171" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;"><?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>http://www.djangoproject.com/documentation/</loc> <changefreq>weekly</changefreq> <priority>0.5</priority> </url> <url> <loc>http://www.djangoproject.com/documentation/0_90/</loc> <changefreq>never</changefreq> <priority>0.1</priority> </url> ... </urlset> </pre> <p class="cn" id="cn172" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">需要了解更多有关 sitemaps 的信息, 请参见 <a class="reference external" tppabs="http://www.sitemaps.org/" style="color:#AB5603;">http://www.sitemaps.org/</a>.</p><p class="cn" id="cn173" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">Django sitemap 框架允许你用 Python 代码来表述这些信息,从而自动创建这个XML文件。 要创建一个站点地图,你只需要写一个`` Sitemap`` 类,并且在URLconf中指向它。</p><div class="section" id="id10" style="margin:0px;padding:0px;"><span id="cn174"></span> <h3 class="cn" id="cn174" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">安装</h3><p class="cn" id="cn175" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">要安装 sitemap 应用程序, 按下面的步骤进行:</p><ol class="arabic simple" style="margin:0px;padding:0px 0px 0px 30px;list-style-position:initial;list-style-image:initial;"><li class="cn" id="cn176" style="margin:0px 0px 0.4em;padding:0px;position:relative;"><p class="first cn" id="cn176" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">将 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'django.contrib.sitemaps'</tt> 添加到您的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">INSTALLED_APPS</tt> 设置中.</p></li></ol><ol class="arabic simple" start="2" style="margin:0px;padding:0px 0px 0px 30px;list-style-position:initial;list-style-image:initial;"><li class="cn" id="cn177" style="margin:0px 0px 0.4em;padding:0px;position:relative;"><p class="first cn" id="cn177" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">确保 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'django.template.loaders.app_directories.load_template_source'</tt> 在您的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">TEMPLATE_LOADERS</tt> 设置中。 默认情况下它在那里, 所以, 如果你已经改变了那个设置的话, 只需要改回来即可。</p></li></ol><ol class="arabic simple" start="3" style="margin:0px;padding:0px 0px 0px 30px;list-style-position:initial;list-style-image:initial;"><li class="cn" id="cn178" style="margin:0px 0px 0.4em;padding:0px;position:relative;"><p class="first cn" id="cn178" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">确定您已经安装了 sites 框架 (参见第14章).</p></li></ol><p class="cn" id="cn179" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">Note</p><p class="cn" id="cn180" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">sitemap 应用程序没有安装任何数据库表. 它需要加入到 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">INSTALLED_APPS</tt> 中的唯一原因是: 这样<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">load_template_source</tt> 模板加载器可以找到默认的模板. The only reason it needs to go into<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">INSTALLED_APPS</tt> is so the <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">load_template_source</tt> template loader can find the default templates.</p></div><div class="section" id="initialization" style="margin:0px;padding:0px;"><span id="cn181"></span> <h3 class="cn" id="cn181" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">Initialization</h3><p class="cn" id="cn182" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">要在您的Django站点中激活sitemap生成, 请在您的 URLconf 中添加这一行:</p> <pre class="cn literal-block" id="cn184" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) </pre> <p class="cn" id="cn185" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">This line tells Django to build a sitemap when a client accesses <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">/sitemap.xml</tt> . Note that the dot character in <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemap.xml</tt> is escaped with a backslash, because dots have a special meaning in regular expressions.</p><p class="cn" id="cn186" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">sitemap文件的名字无关紧要,但是它在服务器上的位置却很重要。 搜索引擎只索引你的sitemap中当前URL级别及其以下级别的链接。 用一个实例来说,如果 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemap.xml</tt> 位于你的根目录,那么它将引用任何的URL。 然而,如果你的sitemap位于 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">/content/sitemap.xml</tt> ,那么它只引用以 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">/content/</tt> 打头的URL。</p><p class="cn" id="cn187" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">sitemap视图需要一个额外的必须的参数: <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">{'sitemaps': sitemaps}</tt> . <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemaps</tt> should be a dictionary that maps a short section label (e.g., <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">blog</tt> or <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">news</tt> ) to its <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> class (e.g., <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">BlogSitemap</tt> or <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">NewsSitemap</tt> ). It may also map to an <em>instance</em> of a <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> class (e.g., <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">BlogSitemap(some_var)</tt> ).</p></div><div class="section" id="id11" style="margin:0px;padding:0px;"><span id="cn188"></span> <h3 class="cn" id="cn188" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">Sitemap 类</h3><p class="cn" id="cn189" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 类展示了一个进入地图站点简单的Python类片断.例如,一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 类能展现所有日志入口,而另外一个能够调度所有的日历事件。 For example, one <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> class could represent all the entries of your weblog, while another could represent all of the events in your events calendar.</p><p class="cn" id="cn190" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">在最简单的例子中,所有部分可以全部包含在一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemap.xml</tt> 中,也可以使用框架来产生一个站点地图,为每一个独立的部分产生一个单独的站点文件。</p><p class="cn" id="cn191" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 类必须是 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.contrib.sitemaps.Sitemap</tt> 的子类. 他们可以存在于您的代码树的任何地方。</p><p class="cn" id="cn192" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">例如假设你有一个blog系统,有一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Entry</tt> 的model,并且你希望你的站点地图包含所有连到你的blog入口的超链接。 你的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 类很可能是这样的:</p> <pre class="cn literal-block" id="cn194" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from django.contrib.sitemaps import Sitemap from mysite.blog.models import Entry class BlogSitemap(Sitemap): changefreq = "never" priority = 0.5 def items(self): return Entry.objects.filter(is_draft=False) def lastmod(self, obj): return obj.pub_date </pre> <p class="cn" id="cn195" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">声明一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 和声明一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 看起来很类似;这都是预先设计好的。</p><p class="cn" id="cn196" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">如同 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Feed</tt> 类一样, <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 成员也既可以是方法,也可以是属性。 想要知道更详细的内容,请参见上文 《一个复杂的例子》章节。</p><p class="cn" id="cn197" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 类可以定义如下 方法/属性:</p><blockquote style="margin:1em 0px;padding:0px 1em;line-height:1.2em;font-family:'Trebuchet MS', sans-serif;border-left-width:2px;border-left-style:solid;border-left-color:#94DA3A;color:#333333 !important;"><p class="cn" id="cn198" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items</tt> (<strong>必需</strong> ):提供对象列表。 框架并不关心对象的 <em>类型</em> ;唯一关心的是这些对象会传递给 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">location()</tt>, <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">lastmod()</tt> , <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">changefreq()</tt> ,和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">priority()</tt> 方法。</p><p class="cn" id="cn199" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">location</tt> (可选): 给定对象的绝对URL。 绝对URL不包含协议名称和域名。 下面是一些例子:</p><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn200" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn200" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">好的: <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'/foo/bar/'</tt> <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'/foo/bar/'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn201" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn201" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">差的: <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'example.com/foo/bar/'</tt> <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'example.com/foo/bar/'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn202" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn202" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">Bad: <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'http://example.com/foo/bar/'</tt> </p></li></ul><p class="cn" id="cn203" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;">如果没有提供 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">location</tt> , 框架将会在每个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">items()</tt> 返回的对象上调用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">get_absolute_url()</tt> 方法.</p><p class="cn" id="cn204" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">lastmod</tt> (可选): 对象的最后修改日期, 作为一个Python <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">datetime</tt> 对象. The object’s last modification date, as a Python <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">datetime</tt> object.</p><p class="cn" id="cn205" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">changefreq</tt> (可选): 对象变更的频率。 可选的值如下(详见Sitemaps文档):</p><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn206" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn206" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'always'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn207" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn207" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'hourly'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn208" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn208" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'daily'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn209" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn209" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'weekly'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn210" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn210" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'monthly'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn211" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn211" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'yearly'</tt> </p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn212" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn212" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'never'</tt> </p></li></ul><p class="cn" id="cn213" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">priority</tt> (可选): 取值范围在 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">0.0</tt> and <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">1.0</tt> 之间,用来表明优先级。</p></blockquote></div><div class="section" id="id12" style="margin:0px;padding:0px;"><span id="cn214"></span> <h3 class="cn" id="cn214" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">快捷方式</h3><p class="cn" id="cn215" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">sitemap框架提供了一些常用的类。 在下一部分中会看到。</p><div class="section" id="flatpagesitemap" style="margin:0px;padding:0px;"><span id="cn216"></span> <h4 class="cn" id="cn216" style="margin:1.4em 0px 0.2em;padding:0px;font-size:15px;color:#487858;position:relative;">FlatPageSitemap</h4><p class="cn" id="cn217" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.contrib.sitemaps.FlatPageSitemap</tt> 类涉及到站点中所有的flat page,并在sitemap中建立一个入口。 但仅仅只包含 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">location</tt> 属性,不支持 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">lastmod</tt> , <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">changefreq</tt> ,或者 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">priority</tt> 。</p><p class="cn" id="cn218" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">参见第16章获取有关flat page的更多的内容.</p></div><div class="section" id="genericsitemap" style="margin:0px;padding:0px;"><span id="cn219"></span> <h4 class="cn" id="cn219" style="margin:1.4em 0px 0.2em;padding:0px;font-size:15px;color:#487858;position:relative;">GenericSitemap</h4><p class="cn" id="cn220" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">GenericSitemap</tt> 与所有的通用视图一同工作(详见第9章)。</p><p class="cn" id="cn221" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">你可以如下使用它,创建一个实例,并通过 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">info_dict</tt> 传递给通用视图。 唯一的要求是字典包含 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">queryset</tt> 这一项。 也可以用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">date_field</tt> 来指明从 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">queryset</tt> 中取回的对象的日期域。 这会被用作站点地图中的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">lastmod</tt>属性。</p><p class="cn" id="cn222" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">下面是一个使用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">FlatPageSitemap</tt> and <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">GenericSiteMap</tt> (包括前面所假定的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Entry</tt> 对象)的URLconf:</p> <pre class="cn literal-block" id="cn224" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from django.conf.urls.defaults import * from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap from mysite.blog.models import Entry info_dict = { 'queryset': Entry.objects.all(), 'date_field': 'pub_date', } sitemaps = { 'flatpages': FlatPageSitemap, 'blog': GenericSitemap(info_dict, priority=0.6), } urlpatterns = patterns('', # some generic view using info_dict # ... # the sitemap (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) ) </pre> </div></div><div class="section" id="id13" style="margin:0px;padding:0px;"><span id="cn225"></span> <h3 class="cn" id="cn225" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">创建一个Sitemap索引</h3><p class="cn" id="cn226" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">sitemap框架同样可以根据 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemaps</tt> 字典中定义的单独的sitemap文件来建立索引。 用法区别如下:</p><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn227" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn227" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">您在您的URLconf 中使用了两个视图: <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.contrib.sitemaps.views.index</tt> 和<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.contrib.sitemaps.views.sitemap</tt> . `` django.contrib.sitemaps.views.index`` 和`` django.contrib.sitemaps.views.sitemap``</p></li></ul><ul class="simple" style="margin:0.6em 0px 1em;padding:0px 0px 0.1em 30px;list-style:none;"><li class="cn" id="cn228" style="margin:0px 0px 0.4em;padding:0px;list-style-type:square;position:relative;"><p class="first cn" id="cn228" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.contrib.sitemaps.views.sitemap</tt> 视图需要带一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">section</tt> 关键字参数.</p></li></ul><p class="cn" id="cn229" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">这里是前面的例子的相关的 URLconf 行看起来的样子:</p> <pre class="cn literal-block" id="cn231" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">(r'^sitemap.xml$', 'django.contrib.sitemaps.views.index', {'sitemaps': sitemaps}), (r'^sitemap-(?P<section>.+).xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}) </pre> <p class="cn" id="cn232" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">这将自动生成一个 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemap.xml</tt> 文件, 它同时引用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemap-flatpages.xml</tt> 和 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemap-blog.xml</tt> . <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">Sitemap</tt> 类和<tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemaps</tt> 目录根本没有更改.</p></div><div class="section" id="google" style="margin:0px;padding:0px;"><span id="cn233"></span> <h3 class="cn" id="cn233" style="margin:1.4em 0px 0.6em;padding:0px;font-size:18px;font-weight:normal;line-height:1.2em;color:#092E20;position:relative;">通知Google</h3><p class="cn" id="cn234" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">当你的sitemap变化的时候,你会想通知Google,以便让它知道对你的站点进行重新索引。 框架就提供了这样的一个函数: <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.contrib.sitemaps.ping_google()</tt> 。</p><p class="cn" id="cn235" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;"><tt class="docutils literal" style="white-space:nowrap;color:#234F32;">ping_google()</tt> 有一个可选的参数 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">sitemap_url</tt> ,它应该是你的站点地图的URL绝对地址(例如:</p><p class="cn" id="cn236" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">如果不能够确定你的sitemap URL, <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">ping_google()</tt> 会引发 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">django.contrib.sitemaps.SitemapNotFound</tt> 异常。</p><p class="cn" id="cn237" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">我们可以通过模型中的 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">save()</tt> 方法来调用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">ping_google()</tt> :</p> <pre class="cn literal-block" id="cn239" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">from django.contrib.sitemaps import ping_google class Entry(models.Model): # ... def save(self, *args, **kwargs): super(Entry, self).save(*args, **kwargs) try: ping_google() except Exception: # Bare 'except' because we could get a variety # of HTTP-related exceptions. pass </pre> <p class="cn" id="cn240" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">一个更有效的解决方案是用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">cron</tt> 脚本或任务调度表来调用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">ping_google()</tt> ,该方法使用Http直接请求Google服务器,从而减少每次调用 <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">save()</tt> 时占用的网络带宽。 The function makes an HTTP request to Google’s servers, so you may not want to introduce that network overhead each time you call <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">save()</tt>.</p><p class="cn" id="cn241" style="margin-top:0.6em;margin-bottom:1em;padding:0px 0px 0.1em;font-size:14px;position:relative;line-height:1.8 !important;color:#333333 !important;">Finally, if <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">'django.contrib.sitemaps'</tt> is in your <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">INSTALLED_APPS</tt> , then your <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">manage.py</tt> will include a new command, <tt class="docutils literal" style="white-space:nowrap;color:#234F32;">ping_google</tt> . This is useful for command-line access to pinging. For example:</p> <pre class="cn literal-block" id="cn243" style="padding:0.3em 0.4em;font-size:medium;border-style:solid;border-color:#94DA3A;border-width:1px 0px;overflow:hidden;width:682px;color:#234F32;position:relative;font-family:Anonymous, Consolas, 'Courier New' !important;background:#E0FFB8;">python manage.py ping_google /sitemap.xml</pre> </div></div>

欢迎转载但请注明出处及链接,商业媒体使用请联系编辑(QQ 363630845)。
第十三章,Django,输出,非HTML
正在加载中……