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. response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = 'attachment; filename="somefilename.csv"' writer = csv.writer(response) writer.writerow(['First row', 'Foo', 'Bar', 'Baz']) writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"]) 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. response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = 'attachment; filename="somefilename.csv"' # The data is hard-coded here, but you could load it from a database or # some other source. csv_data = ( ('First row', 'Foo', 'Bar', 'Baz'), ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"), ) t = loader.get_template('my_template_name.txt') c = Context({ 'data': csv_data, }) response.write(t.render(c)) return response
{% 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. response = HttpResponse(mimetype='application/pdf') response['Content-Disposition'] = 'attachment; filename="somefilename.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
最后的showPage()和save()对于pdf文件来说是很重要的,其他的注意事项和输出csv文件的差不多,可以参考着看
复杂的pdf
如果你想创建复杂的pdf,考虑使用cStringIO临时存放你的pdf文件
# Fall back to StringIO in environments where cStringIO is not available try: from cStringIO import StringIO except ImportError: from StringIO import StringIO from reportlab.pdfgen import canvas from django.http import HttpResponse def some_view(request): # Create the HttpResponse object with the appropriate PDF headers. response = HttpResponse(mimetype='application/pdf') response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"' 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. 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. pdf = buffer.getvalue() buffer.close() response.write(pdf) return response