# Django Step by Step (四)
## 1 引言
经过前几节的学习,我想大家应该比较熟悉 Django 的大致开发流程:
* 增加 view 方法
* 增加模板
* 修改 urls.py
就是这样。剩下的就是挖掘 Django 提供的其它的能力。在我们还没有进入模型(model)之前还是再看一看外围的东西,再更进一步体验 Django 吧。
在 Django 中我看到了一个生成 csv 格式的文档(Outputting CSV dynamically),非常好,它没有数据库,正好用来做演示。
更进一步,现在我的需求就是提供 excel 格式文件的下载。
我们会在原来 list(表格) 例子基础上进行演示,步骤就是上面的流程。
## 2 修改 templates/list.html
在文件最后增加:
```html
<p><a href="/xls/address/">Excel格式下载</a></p>
```
它将显示为一个链接,它所指向的链接将用来生成 Excel 文件。
## 3 在newtest下增加 xls_test.py
```python
from django.http import HttpResponse
from django.template import loader, Context
address = [
('张三', '地址一'),
('李四', '地址二')
]
def output(request, filename):
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename=%s.xls' % filename
t = loader.get_template('xls.html')
c = Context({
'data': address,
})
response.write(t.render(c))
return response
```
这里使用的东西多了一些。这里没有 `render_to_response` 了,而是演示了一个完整的从头进行模板解析的处理过程。为什么需要这样,因为我们需要修改 `response` 对象的值,而 `render_to_response` 封装了它使得我们无法修改。从这里我们也可以看到,在调用一个方法时, Django 会传入一个 `request` 对象,在返回时,你需要将内容写入 `response` ,必要时修改它的某些属性。更详细的建议你参考 django 所带的 request_response 文档,里面详细描述了两个对象的内容,并且还可以在交互环境下进行测试,学习非常方便。
这里 `address` 不再是字典的列表,而是 tuple 的列表。让人高兴的是, Django 的模板除了可以处理字典,还可以处理序列,而且可以处理序列中的元素。一会在模板定义中我们会看到。
这里 `output()` 是我们希望 Django 调用的方法,不再是 `index()` 了。(不能老是一样的呀。)而且它与前面的 `index()` 不同,它带了一个参数。这里主要是想演示 url 的参数解析。因此你要注意,这个参数一定是放在 url 上的。它表示输出文件名。
```python
response = HttpResponse(mimetype='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename=%s.xls' % filename
```
这两行是用来处理输出类型和附件的,以前我也没有用过,这回也学到了。它表明返回的是一个Excel格式的文件。
```python
t = loader.get_template('xls.html')
c = {
'data': address,
}
response.write(t.render(c))
```
这几行就是最原始的模板使用方法。先通过 `loader` 来找到需要的模板,然后生成一个 template 对象,再生成一个 `Context` 对象,它就是一个字典集。然后 `t.render(c)` 这个用来对模板和提供的变量进行合并处理,生成最终的结果。最后调用 `response.write()` 将内容写入。
## 4 增加 templates/xls.html
```html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
</head>
<body>
<table>
{% for row in data %}
<tr>
<td>{{ row.0|addslashes}}</td>
<td>{{ row.1|addslashes}}</td>
</tr>
{% endfor %}
</body>
</html>
```
使用了一个 for 循环。这里 `data` 与上面的 `Context` 的 `data` 相对应。因为 `data` 是一个列表,它的每行是一个 tuple ,因此 `row.0`, `row.1` 就是取 tuple 的第一个和第二个元素。`|` 是一个过滤符,它表示将前一个的处理结果作为输入传入下一个处理。因此 Django 的模板很强大,使用起来也非常直观和方便。 `addslashes` 是 Django 模板内置的过滤 Tag ,它用来将结果中的特殊字符加上反斜线。
同时我们注意到,每个 `{{}}` 前后都有一个双引号,这样就保证每个字符串使用双引号引起来。然后在第一个与第二个元素之间还使用了逗号分隔。最后 `endfor` 在下一行,表示上面每行模板后有一个回车。
Django 还允许你自定义 Tag ,在 The Django template language: For Python programmers 文档中有描述,其实是很简单的。
## 5 修改 urls.py
```python
from django.conf.urls import url
from django.contrib import admin
from . import helloworld, add, list, xls_test
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', helloworld.index),
url(r'^add/$', add.index),
url(r'^list/$', list.index),
url(r'^xls/(?P<filename>\w+)/$', xls_test.output),
]
```
增加了 xls 的 url 映射。
上面的正则表达式有些复杂了,因为有参数的处理在里面。 `(?P<filename>\w+)` 这是一个将解析结果起名为 `filename` 的正则表达式,它完全符合 Python 正则表达式的用法。在最新的 Django 中,还可以简化一下: `(\w+)` 。但这样需要你的参数是按顺序传入的,在一个方法有多个参数时一定要注意顺序。
还记得吗?我们的链接是写成 `/xls/address/` ,因此上面实际上会变成对 `xls_test.output(filename='address')` 的调用。
## 6 启动 server
看一下结果吧。点击链接,浏览器会提示你保存文件的。
很简单吧。但这里面的内容其实也不少,而且许多地方都有很大的扩展空间。
- 开始学习
- 搭建Python开发环境
- 简明Python教程
- 致敬
- 前言
- 关于Python
- 安装
- 第一步
- 基础
- 运算符和表达式
- 控制流
- 函数
- 模块
- 数据结构
- 实战案例
- 面向对象编程
- 输入与输出
- 异常处理
- 标准库
- 更多
- 继续学习
- 附录:免费/自由和开放源码软件
- 附录: 关于
- 附录: 版本历史
- 附录: 翻译
- 附录: 参与翻译工作
- 反馈
- Django Step Sy Step
- 第一讲 从简单到复杂
- 第二讲 做加法的例子
- 第三讲 使用Template
- 第四讲 生成csv格式文件
- 第五讲 session示例
- 第六讲 wiki的例子
- 第七讲 通讯录的例子
- 第八讲 文件导入和导出
- 第九讲 通讯录的美化
- 第十讲 扩展django的模板
- 第十一讲 用户管理
- 第十二讲 搜索和部署
- 第十三讲 Ajax的实现(一)
- 第十四讲 Ajax的实现(二)
- 第十五讲 i18n的一个简单实现
- 第十六讲 自定义Calendar Tag
- 第十七讲 View,Template和Tag
- Django开发实战
- Python开发规范
- Django项目的gitignore
- 怎样配置开发环境的settings
- 如何使用Django和Vue.js构建项目
- 使用WebSocket开发网页聊天室
- 怎样使Django Admin显示中文
- 怎样使Model在Admin界面中显示中文
- 使用Django Admin怎样上传并显示图片
- 解决Django模板和Vue指令花括号冲突的问题
- 使用Django和Vue开发微信公众号
- 使用Django和Vue调用微信JSSDK开发微信支付