Django 拥有一些 便利的内建工具帮助你生成常见的非HTML 内 容:
- RSS/Atom 聚合文件
- 站点地图 ( 一个XML 格式文件, 最初由Google 开发, 用于给搜索引擎提示线索)
基础: 视图和MIME 类型
从一个视图返回一个非 HTML 内 容的关键是在构造一个 HttpResponse 类 时, 需要指定 mimetype 参数。 通
过改变 MIME 类型, 我们可以通知浏览器将要返回的数据是另一种类 型。
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”)
生成 CSV 文件
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
生成 PDF 文件
安装 ReportLab
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
复杂的 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
其它的可能性
- ZIP 文件 ython 标准库中包含有 zipfile 模块, 它可以读和写压缩的 ZIP 文件。 它可以用于按需生成一些文件的压缩包, 或 者在需要时压缩大的文档。 如果是 TAR 文 件则可以使用标准库 tarfile 模 块。
- 动态图片 : Python 图 片处理库 (PIL; http://www.pythonware.com/products/pil/) 是极好的生成图片(PNG, JPEG, GIF 以及其它许多格 式) 的工具。 它可以用于自动为图片生成缩略图, 将多 张图片压缩到单独的框架中, 或者是做基 于 Web 的图片处理。
- 图表 : Python 有许 多出色并且强大的图表库用以绘制图表, 按 需地图, 表格等。 我们不可能将它们全部列出, 所以下面列 出的是个中的翘楚。
- matplotlib (http://matplotlib.sourceforge.net/) 可以用于生成通常是由 matlab 或者 Mathematica 生成的高质量图表。
- pygraphviz (https://networkx.lanl.gov/wiki/pygraphviz) 是一个 Graphviz 图形布局的工具(http://graphviz.org/) 的 Python 接口, 可以用于生成结构化的图表和网络。
内容聚合器应用框架
初始化
为了在您的Django 站点中激 活syndication feeds, 添 加如下的 URLconf:
(r’^feeds/(?P<url>.*)/$’, ‘django.contrib.syndication.views.feed’,
{‘feed_dict’: feeds}
),
一个简单的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’)
要注意的重要的事情如下所示:
- 子类 django.contrib.syndication.feeds.Feed .
- title , link , 和 description 对应一个 标准 RSS 里的 <title> , <link> , 和 <description> 标签.
- items() 是一个方法, 返回一个用以包含在包含在feed 的 <item> 元素里的 list 虽然例子里用Djangos database API 返回的 NewsItem 对象, items() 不一定必须返回 model 的实例 Although this example returns Entry objects using Django’s database API, items() doesn’t have to return model instances
一个更复杂的Feed
举个例子会澄清一切。 下面是每个地区特定的feeds:
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]
以下是RSS 框架的基本算法, 我们假设通过URL /rss/beats/0613/ 来访问 这个类:
指定Feed 的类型
默认情况下, 聚合框架生成RSS 2.0. 要改变这样的情况, 在 Feed 类中添加一个 feed_type 属性.
闭包
语言
URLs
同时发布Atom and RSS
只需创建一个你的 feed 类 的子类, 然后修改 feed_type , 并且更新URLconf 内容。
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
这是与之相对应那个的URLconf:
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}),
# …
)
Sitemap 框架
安装
要安装 sitemap 应用程 序, 按下面的步骤进行:
1. 将 ‘django.contrib.sitemaps’ 添 加到您的 INSTALLED_APPS 设 置中.
2. 确保 ‘django.template.loaders.app_directories.load_template_source’ 在您的 TEMPLATE_LOADERS 设置中。 默认情况下它在那里, 所 以, 如果你已经改变了那个设置的话, 只需要改回来即可。
3. 确定您已经安装了 sites 框架 ( 参见第14 章).
要在您的Django 站点中激活sitemap 生成, 请在您的 URLconf 中添加这一行:
(r’^sitemap/.xml$’, ‘django.contrib.sitemaps.views.sitemap’, {’sitemaps’: sitemaps})