Создание CSV-файла с помощью Django (динамическое содержимое)

внутри моего view.py, у меня есть две функции, одна из которых обрабатывает ввод из формы и выводит отфильтрованный список, а другая, которая должна экспортировать этот список в 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   

Я не уверен, как получить объект QuerySet из моей первой функции, которая содержит список элементов, которые я хочу в моем CSV и использовать его в моей функции export_to_csv. Или лучший способ объединить эти две функции и заставить пользователя нажать на флажок, хочет ли он/она загрузить файл CSV. Любая помощь будет оценена.

4 ответов


Я бы рекомендовал объединить их в одну функцию просмотра, которая принимает дополнительный параметр:

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"),

IMHO, лучше всего было бы объединить их и генерировать данные 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'))

--

приведенный пример кода предполагает, что набор запросов задан в данных сеанса, что может вызвать множество ошибок, а также проблемы безопасности. Если вы храните сеансы в своей базе данных, вы можете в конечном итоге читать данные, просто чтобы запишите его обратно в гораздо менее эффективной форме.


Я нашел способ сделать это, который отличается от кнутина. Я объявил пустой список с именем csv_list = [] вне моих функций или глобальной переменной.

в моей основной функции (той, которая обрабатывает и фильтрует на основе пользовательского ввода) я делаю этот csv_list глобальным, чтобы он был установлен в "обновленную" версию queryset. Затем, чтобы создать csv, это так же просто, как: для вызова в csv_list: писатель.writerow([звонок.ГРЦ, звоните.летнее время]) ответ

Это теперь работает разумно.


следующее принимает в Django queryset и выплевывает CSV-файл.

использование::

из utils импортировать dump2csv

из dummy_app.импорт моделей *

qs = DummyModel.объекты.all ()

dump2csv.dump(qs,'./ данные / дамп.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)