2010-11-01 31 views
7

在我的view.py中,我有两个函数,一个处理来自表单的输入并输出过滤列表,另一个应该将该列表导出为CSV。使用Django生成CSV文件(动态内容)

这是我的第一个函数的返回:

return render_to_response('templateX.html', 
{ 
'queryset': queryset, 
'filter_form': filter_form, 
'validated': validated, 
}, 
context_instance = RequestContext(request) 
) 

这里是出口功能:

def export_to_csv(request): 
    # get the response object, this can be used as a stream. 
    response = HttpResponse(mimetype='text/csv') 
    # force download. 
    response['Content-Disposition'] = 'attachment;filename=export.csv' 
    # the csv writer 
    writer = csv.writer(response) 
    qs = request.session['queryset'] 
    for cdr in qs: 
     writer.writerow([cdr['calldate'], cdr['src'], cdr['dst'], ]) 
    return response 

我不知道如何从我的第一个功能得到查询集,其中包含我想要的CSV项目列表,并在我的export_to_csv函数中使用它。 或者最好的办法是结合这两个功能,并让用户点击一个复选框,无论他/她想下载一个CSV文件。 任何帮助,将不胜感激。

回答

7

我建议这些组合成这需要一个额外的参数一个视图功能:

def my_view(request, exportCSV): 
    # ... Figure out `queryset` here ... 

    if exportCSV: 
     response = HttpResponse(mimetype='text/csv') 
     response['Content-Disposition'] = 'attachment;filename=export.csv' 
     writer = csv.writer(response) 
     for cdr in queryset: 
      writer.writerow([cdr['calldate'], cdr['src'], cdr['dst'], ]) 
     return response 
    else: 
     return render_to_response('templateX.html', {'queryset': queryset, 
      'filter_form': filter_form, 'validated': validated}, 
      context_instance = RequestContext(request)) 

然后,在你urls.py,把这样的事情在你的urlpatterns

url(r'^form', 'my_view', {"exportCSV": False}, name="form"), 
url(r'^csv', 'my_view', {"exportCSV": True}, name="export"), 
+0

我试过这种方式,但是当我点击我的“导出”按钮,它会转到url:localhost:8000/cdr/export_csv,它会丢失所有的GET请求,因此没有处理queryset,所以我的CSV文件是空的。那么,我的“导出”按钮如何发送所有请求,就好像我点击了我的“搜索”按钮? – chiurox 2010-11-02 00:04:53

+0

您的导出按钮应该:1)定位导出URL并包含查询参数;或者2)作为具有查询参数的表单的一部分,如果需要,可以隐藏字段。由于我不完全清楚你的页面是如何相互关联的,因此我很难提出具体的建议。 – 2010-11-02 04:10:36

+0

是的,我决定按照你描述的方式来做这件事,作为你的第一选择。现在'隐藏的领域',这很有趣,稍后我会遇到类似的情况。 – chiurox 2010-11-03 13:08:35

4

恕我直言,最好的办法是将它们结合起来并从显式查询集中生成CSV数据。这可能再被改写的东西一般像(未测试):

def export_to_csv(request, queryset, fields): 
    response = ... 
    writer = csv.writer(response) 
    for obj in queryset: 
     writer.writerow([getattr(obj, f) for f in fields]) 
    return response 

您可以使用这样的:

def my_view(request): 
    calls = Call.objects.all() 
    return export_to_csv(request, calls, fields = ('calldate', 'src', 'dst')) 

-

您提供的示例代码假定查询集是在会话数据中设置,这可能会导致大量错误以及安全问题。如果将会话存储在数据库中,最终可能会读取数据,只能以效率更低的形式写回数据。

0

我发现了一种做法,它与knutin不同。 我在我的函数或全局变量之外声明了一个名为csv_list = []的空列表。

在我的主要功能(根据用户输入进行处理和过滤的功能)中,我将此csv_list设置为全局,以便将其设置为查询集的“更新”版本。 然后生成CSV,因为它是那么容易: 在csv_list电话: writer.writerow([call.src,call.dst]) 返回响应

它现在的工作相当。

+0

这是危险的使用全局变量通过视图来传递数据; Django可以进行线程化,这可能会在部署时中断。在你自己测试的时候你不会看到这个错误,因为它是基于竞争条件的,所以追踪它会很困难。 – 2010-11-01 23:13:07

+0

您能否详细说明危险性以及它如何在部署中崩溃? – chiurox 2010-11-01 23:18:55

+0

用户1发布您的表单请求。这会调用设置'csv_list'的视图函数。用户2做同样的事情,它又设置'csv_list'。用户1然后导出CSV并通过'csv_list'获取用户2的数据。 – 2010-11-01 23:21:50

0

以下接受一个Django查询集,并吐出一个CSV文件。

用法::

从utils的进口dump2csv

从dummy_app.models导入*

QS = DummyModel.objects。所有()

dump2csv.dump(QS './data/dump.csv')

脚本:

import csv 
from django.db.models.loading import get_model 

def dump(qs, outfile_path): 

    model = qs.model 
writer = csv.writer(open(outfile_path, 'w')) 

headers = [] 
for field in model._meta.fields: 
    headers.append(field.name) 
writer.writerow(headers) 

for obj in qs: 
    row = [] 
    for field in headers: 
     val = getattr(obj, field) 
     if callable(val): 
      val = val() 
     if type(val) == unicode: 
      val = val.encode("utf-8") 
     row.append(val) 
    writer.writerow(row)