2010-11-01 5 views
7

Innerhalb meiner view.py habe ich zwei Funktionen, eine, die Eingabe von einem Formular verarbeitet und eine gefilterte Liste ausgibt, und eine andere, die diese Liste in CSV exportieren soll.Generieren von CSV-Datei mit Django (dynamischer Inhalt)

Hier ist die Rückkehr meiner ersten Funktion:

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

Hier ist die Exportfunktion:

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 

Ich bin nicht sicher, wie die queryset von meiner ersten Funktion zu erhalten, Das enthält eine Liste der Elemente, die ich in meiner CSV-Datei haben möchte, und verwende sie in meiner export_to_csv-Funktion. Oder würde diese beiden Funktionen am besten kombiniert werden und der Benutzer auf ein Kontrollkästchen klicken, ob er eine CSV-Datei herunterladen möchte. Jede Hilfe wäre willkommen.

Antwort

7

Ich würde empfehlen, diese in einer View-Funktion kombiniert, die einen zusätzlichen Parameter nimmt:

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

Dann in Ihrem urls.py, setzen so etwas wie dies in Ihrem urlpatterns:

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

Ich habe es auf diese Weise versucht, aber wenn ich auf meinen "Export" -Button klicke, der zur URL geht: localhost: 8000/cdr/export_csv, verliert es alle GET-Anfragen und als Folge gibt es keine Verarbeitung von queryset, also meine Die CSV-Datei ist leer. Wie kann also mein "Export" -Button alle Anfragen senden, als würde ich auf meinen "Suchen" -Button klicken? – chiurox

+0

Ihre Export-Schaltfläche sollte entweder 1) auf die Export-URL und die Abfrage-Parameter, oder 2) Teil eines Formulars, das die Abfrage-Parameter, als versteckte Felder, wenn nötig. Es ist schwer für mich, eine spezifische Empfehlung zu geben, da ich nicht ganz klar bin, wie Ihre Seiten zueinander stehen. –

+0

Ja, ich habe beschlossen, es so zu machen, wie Sie es als Ihre erste Option beschrieben haben. Nun, "versteckte Felder", das ist interessant, ich werde später darauf schauen, wenn ich auf eine ähnliche Situation stoße. – chiurox

4

IMHO, das Beste wäre, sie zu kombinieren und die CSV-Daten aus einem expliziten Abfrage-Set zu generieren. Dies könnte dann zu etwas allgemein neu geschrieben werden wie (nicht getestet):

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 

, die Sie mögen diese verwenden:

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

-

Der Beispielcode Ihnen zur Verfügung gestellten annimmt die QuerySet ist Stellen Sie in den Sitzungsdaten, die Sie Tonnen von Bugs sowie Sicherheitsprobleme verursachen können. Wenn Sie Sitzungen in Ihrer Datenbank speichern, könnten Sie am Ende Daten lesen, nur um sie in einer viel weniger effizienten Form wiederzugeben.

0

Ich habe einen Weg gefunden, es anders zu machen als Knutins. Ich habe eine leere Liste namens csv_list = [] außerhalb meiner Funktionen oder globalen Variable deklariert.

In meiner Hauptfunktion (die, die basierend auf Benutzereingabe verarbeitet und filtert), mache ich diese csv_list global, so dass es auf die "aktualisierte" Version des Abfrage-Sets gesetzt wird. dann die csv zu erzeugen, ist es so einfach wie: für Anruf in csv_list: writer.writerow ([call.src, call.dst]) return response

Es ist einigermaßen funktioniert jetzt.

+0

Es ist gefährlich, Globals zu verwenden, um Daten über Ansichten passieren ; Django kann eingefädelt werden, und dies wird wahrscheinlich bei der Bereitstellung unterbrochen. Sie werden diesen Bug nicht sehen, während Sie selbst testen, und da er auf einer Race Condition basiert, wird es schwierig sein, ihn zu finden. –

+0

Könnten Sie mehr über die Gefährlichkeit und wie es bei der Bereitstellung brechen könnte? – chiurox

+0

Benutzer 1 sendet eine Anfrage für Ihr Formular. Dies ruft Ihre View-Funktion auf, die 'csv_list' setzt. Benutzer 2 tut dasselbe, was wiederum 'csv_list' setzt. Benutzer 1 exportiert dann die CSV und ruft stattdessen die Daten von Benutzer 2 über 'csv_list' ab. –

0

Die folgende nimmt ein Django-Abfrage-Set auf und spuckt eine CSV-Datei aus.

Usage ::

von utils importieren dump2csv

von dummy_app.models importieren *

qs = DummyModel.objects.alle()

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

Das Skript:

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