Dieses Dokument erklärt, wie man mithilfe von Django-Views dynamisch CSVs (Comma Separated Values) ausgibt. Hierfür kannst du entweder Pythons CSV-Bibliothek oder Djangos Template-System verwenden.
Pythons Standardbibliothek enthält bereits eine CSV-Bibliothek namens csv, die u.a. die Generierung von CSV-Daten auf dateiähnlichen Objekten und somit auch Djangos HttpResponse-Objekten ermöglicht.
Hier ein kurzes Beispiel:
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
Der Code und die Kommentare sollte selbsterklärend sein, ein paar Dinge sollte jedoch hervorgehoben werden:
Alternativ kannst du auch Djangos Template-System für die Generierung von CSV-Daten verwenden. Das ist zwar ein bisschen umständlicher als die Verwendung der csv-Bibliothek, soll hier aber trotzdem der Vollständigkeit wegen beschrieben werden.
Die Idee hier ist, dass du eine Liste von Elementen deinem Template übergibst, welches dann die entsprechende Zeilenformatierung in einer for-Schleife durchführt.
Hier ist ein Beispiel, welches die gleiche CSV-Datei wie oben erzeugt:
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'
# Die Daten sind hier hartkodiert, könnten aber natuerlich auch aus
# einer Datenbank oder einer anderen Quelle stammen.
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
Der einzige Unterschied zum Beispiel von oben ist, dass hier das Template-System anstelle des CSV-Moduls geladen wird. Der restliche Code -- wie zum Beispiel das Setzen des MIME-Types -- ist gleich.
Als nächstes brauchen wir nun das my_template_name.txt-Template mit folgendem Code:
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}
Das Template ist sehr einfach. Es iteriert über die übergebenen Daten und zeigt eine CSV-Zeile für jede übergebene Zeile an. Es verwendet ausserdem den addslashes-Templatefilter, um Probleme mit Anführungszeichen etc. vorzubeugen.
In beiden Beispielen passiert eigentlich nichts wirklich CSV-Spezifisches mit Ausnahme des Ausgabeformats. Du kannst somit beide Methoden für beliebige textbasierte Formate verwenden. Wenn du Binärdaten erzeugen willst, geht das ebenfalls sehr ähnlich, was zum Beispiel in PDFs mit Django erzeugen beschrieben wird.
Mar 01, 2010