2010-11-01 27 views
7

Dentro de mi view.py, tengo dos funciones, una que procesa la entrada desde un formulario y genera una lista filtrada, y otra que se supone que exporta esta lista a CSV.Generar archivo CSV con Django (contenido dinámico)

Aquí es el regreso de mi primera función:

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

Aquí es la función de exportación:

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 

No estoy seguro de cómo obtener el queryset de mi primera función, que contiene una lista de los elementos que quiero en mi CSV y la uso en mi función export_to_csv. O sería la mejor manera combinar estas dos funciones y hacer que el usuario haga clic en una casilla de verificación si desea descargar un archivo CSV. Cualquier ayuda sería apreciada.

Respuesta

7

me gustaría recomendar la combinación de estos en una función de vista que toma un parámetro adicional:

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

Luego, en su urls.py, poner algo como esto en su urlpatterns:

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

Lo probé de esta manera, pero cuando hago clic en mi botón "exportar", que va a la url: localhost: 8000/cdr/export_csv, pierde todas las solicitudes GET y como consecuencia no hay procesamiento de queryset, entonces mi El archivo CSV está vacío. Entonces, ¿cómo puede mi botón "exportar" enviar todas las solicitudes como si estuviera haciendo clic en mi botón "buscar"? – chiurox

+0

Su botón Exportar debe 1) orientar el URL de exportación e incluir los parámetros de consulta, o 2) ser parte de un formulario que tenga los parámetros de consulta, como campos ocultos si es necesario. Es difícil para mí hacer una recomendación específica ya que no tengo muy claro cómo se relacionan sus páginas entre sí. –

+0

Sí, decidí hacerlo de la manera que usted describió como su primera opción. Ahora, 'campos ocultos', eso es interesante, lo veré más adelante cuando me encuentre con una situación similar. – chiurox

4

En mi humilde opinión, lo mejor sería combinarlos y generar los datos CSV desde un queryset explícito. Esto podría ser reescrita para general algo similar (no probado):

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 

que se puede utilizar de esta manera:

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

-

El código de ejemplo que ya ha proporcionado asume el QuerySet es establecer en los datos de la sesión, lo que podría causar toneladas de errores, así como problemas de seguridad. Si almacena sesiones en su base de datos, puede terminar leyendo datos, solo para volver a escribirlos en una forma mucho menos eficiente.

0

Encontré una forma de hacerlo diferente a la de knutin. He declarado una lista vacía llamada csv_list = [] fuera de mis funciones, o variable global.

En mi función principal (la que procesa y filtra en función de la entrada del usuario), hago que esta lista csv_list sea global para que se establezca en la versión "actualizada" del conjunto de preguntas. después para generar el csv, es tan fácil como: para la llamada en csv_list: writer.writerow ([call.src, call.dst]) respuesta de retorno

Está funcionando razonablemente ahora.

+0

Es peligroso utilizar variables globales para pasar los datos a través de puntos de vista ; Django puede ser enhebrado, y esto probablemente se rompa en la implementación. No verá este error mientras prueba por su cuenta, y dado que se basa en una condición de carrera, será difícil rastrearlo. –

+0

¿Podría explicar más sobre la peligrosidad y cómo podría romperse en el despliegue? – chiurox

+0

Usuario 1 publica una solicitud para su formulario. Esto llama a su función de vista que establece 'csv_list'. El usuario 2 hace lo mismo, que nuevamente establece 'csv_list'. El usuario 1 luego exporta el archivo CSV y obtiene los datos del usuario 2 a través de 'csv_list' en su lugar. –

0

La siguiente toma un queryset de Django y escupe un archivo CSV.

Uso ::

de utilidades importar dump2csv

de dummy_app.models import *

Qs = DummyModel.objects.todos()

dump2csv.dump (qs, './data/dump.csv')

El guión:

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) 
Cuestiones relacionadas