django “如何”系列9:三合一:利用遗留的数据库、输出csv和输出pdf

如何集成遗留的数据库

django在适合开发新应用的同时,可以可以集成以前遗留的数据库,下面是如何集成一个已经存在的数据库的流程。

给定你的数据库的参数

你需要告诉django你的数据库连接参数以及数据库的名字,你可以通过修改django配置文件的DATABASES中的default连接来给定你的数据库参数

  • NAME
  • ENGINE
  • USER
  • PASSWORD
  • HOST
  • PORT

自动生成模型

django自带了一个工具inspectdb,这个工具可以通过反溯一个已经存在的数据库来创建一个模型

python manage.py inspectdb

你可以直接使用重定向输出到一个文件里面

python manage.py inspectdb > models.py

生成其他的核心表格

inspectdb指定反溯创建已经有的数据库表,我们仍然需要创建其他的核心表格,比如admin权限等等

python manage.py syncdb

测试和调整

通过各种方法测试和调整这些模型知道符合你的要求。建议通过django数据库api访问数据,通过django的admin站点编辑数据和根据需要调整你的模型文件。

使用django输出csv

这里主要介绍如何动态的使用django的视图函数去输出csv文件。你可以是用python的csv库或者django模板系统

使用python的csv库

python自带一个csv库csv。在django中使用这个库的关键在于:csv模块的csv创建能力作用于类文件对象,django的HttpResponse对象就是类文件对象。下面是一个例子:

import csv
from django.http import HttpResponse def some_view(request):

# Create the HttpResponse object with the appropriate CSV header.<br/>
response = HttpResponse(mimetype=&#39;text/csv&#39;)<br/>
response[&#39;Content-Disposition&#39;] = &#39;attachment; filename=&#34;somefilename.csv&#34;&#39;

writer = csv.writer(response)

writer.writerow([&#39;First row&#39;, &#39;Foo&#39;, &#39;Bar&#39;, &#39;Baz&#39;])<br/>
writer.writerow([&#39;Second row&#39;, &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;&#34;Testing&#34;&#39;, &#34;Here&#39;s a quote&#34;])

return response

代码和注释是一目了然的,但是还是有一些东西值得一提:

  • 响应得到一个特别的MIME类型‘text/csv’,如果没有这个的话,浏览器可能把输出解释成一个html,那是一个丑陋可怕的官网文章。
  • 响应得到一个额外的Content-Disposition头部,包含了csv文件的文件名,这个文件名在另存为窗口会用到
  • 钩进csv生成器api是非常简单的,csv.writer接受一个类文件对象,而HttpResponse对象刚好符合
  • writer.writerow接受一个可迭代的对象(列表或者元组)
  • csv模块为你注意了引号,需要把原始的字符串穿进去就好了

处理Unicode

python的csv模块不支持Unicode输入,因为django只在内部使用unicode,这意味着,从某些源(比如HttpReuqest)的字符串是有潜在问题的。下面是一些处理的方法:

  • 手工把所有的unicode对象编码成一个兼容的编
  • 使用UnicodeWriter类
  • 使用python-unicode 模块

使用模板系统输出csv

想法:给你的模板传递一个对象的列表,然后再模板中使用for循环输出逗号。

这是一个例子:

from django.http import HttpResponse
from django.template import loader, Context def some_view(request):

# Create the HttpResponse object with the appropriate CSV header.<br/>
response = HttpResponse(mimetype=&#39;text/csv&#39;)<br/>
response[&#39;Content-Disposition&#39;] = &#39;attachment; filename=&#34;somefilename.csv&#34;&#39;

The data is hard-coded here, but you could load it from a database or

# some other source.<br/>
csv_data = (<br/>
    (&#39;First row&#39;, &#39;Foo&#39;, &#39;Bar&#39;, &#39;Baz&#39;),<br/>
    (&#39;Second row&#39;, &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;&#34;Testing&#34;&#39;, &#34;Here&#39;s a quote&#34;),<br/>
)

t = loader.get_template(‘my_template_name.txt’)

c = Context({<br/>
    &#39;data&#39;: csv_data,<br/>
})<br/>
response.write(t.render(c))<br/>
return response</pre>

{% for row in data %}“{{ row.0|addslashes }}”, “{{ row.1|addslashes }}”, “{{ row.2|addslashes }}”, “{{ row.3|addslashes }}”, “{{ row.4|addslashes }}”
{% endfor %}
使用django输出pdf

django使用一个优秀的开源python库ReportLab来输出pdf文件的

安装ReportLab

可以直接去网上搜索下载或者直接用命令行安装都可以

http://www.reportlab.com/software/opensource/rl-toolkit/download/

安装完成后直接导入就可以使用了

 import reportlab

在视图函数中使用

类似csv模块,ReportLab的api也是作用于类文件对象的,而django的HttpResponse对象也是类文件对象,下面是一个简单的例子:

from reportlab.pdfgen import canvas
from django.http import HttpResponse def some_view(request):

# Create the HttpResponse object with the appropriate PDF headers.<br/>
response = HttpResponse(mimetype=&#39;application/pdf&#39;)<br/>
response[&#39;Content-Disposition&#39;] = &#39;attachment; filename=&#34;somefilename.pdf&#34;&#39;

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.<br/>
p.drawString(100, 100, &#34;Hello world.&#34;)

Close the PDF object cleanly, and we’re done.

p.showPage()<br/>
p.save()<br/>
return response</pre>

最后的showPage()和save()对于pdf文件来说是很重要的,其他的注意事项和输出csv文件的差不多,可以参考着看

复杂的pdf

如果你想创建复杂的pdf,考虑使用cStringIO临时存放你的pdf文件

# Fall back to StringIO in environments where cStringIO is not available
try:

from cStringIO import StringIO<br/>

except ImportError:

from StringIO import StringIO<br/>

from reportlab.pdfgen import canvas
from django.http import HttpResponse def some_view(request):

# Create the HttpResponse object with the appropriate PDF headers.<br/>
response = HttpResponse(mimetype=&#39;application/pdf&#39;)<br/>
response[&#39;Content-Disposition&#39;] = &#39;attachment; filename=&#34;somefilename.pdf&#34;&#39;

buffer = StringIO()

Create the PDF object, using the StringIO object as its “file.”

p = canvas.Canvas(buffer)

Draw things on the PDF. Here‘s where the PDF generation happens.

# See the ReportLab documentation for the full list of functionality.<br/>
p.drawString(100, 100, &#34;Hello world.&#34;)

Close the PDF object cleanly.

p.showPage()<br/>
p.save()

Get the value of the StringIO buffer and write it to the response.

pdf = buffer.getvalue()<br/>
buffer.close()<br/>
response.write(pdf)<br/>
return response</pre>