# Τεκμηρίωση του Django - 6.0.7

# How to create CSV output

Αυτό το άρθρο εξηγεί πως να εξάγετε αρχεία CSV (Comma Separated Values), δυναμικά, χρησιμοποιώντας τα Django views. Για να το κάνετε αυτό, μπορείτε είτε να χρησιμοποιήσετε την βιβλιοθήκη CSV της Python ή το σύστημα template του Django.

## Χρησιμοποιώντας τη βιβλιοθήκη CSV της Python

Η Python έρχεται με μια βιβλιοθήκη, `csv`. Το κλειδί για να την χρησιμοποιήσετε με το Django είναι ότι η δυνατότητα της δημιουργίας CSV του module `csv` ενεργεί πάνω σε objects που μοιάζουν με αρχεία και τα objects της κλάσης `HttpResponse` του Django είναι objects που μοιάζουν με αρχεία.

Ορίστε ένα παράδειγμα:

    import csv
    from django.http import HttpResponse

    def some_view(request):
        # Create the HttpResponse object with the appropriate CSV header.
        response = HttpResponse(
            content_type="text/csv",
            headers={"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

Παρόλο που ο κώδικας και τα σχόλια είναι αρκετά επεξηγηματικά, θα πρέπει να αναφέρουμε μερικά πράγματα:

- Το response παίρνει έναν ειδικό τύπο MIME, text/csv. Αυτό λέει στους browsers ότι το έγγραφο είναι ένα αρχείο CSV, παρά ένα αρχείο HTML. Αν δεν το προσδιορίσετε, οι browsers, πιθανόν, να ερμηνεύσουν το reponse ως ένα αρχείο HTML, που σημαίνει ότι το αποτέλεσμα θα είναι όχι μόνο άσχημο αλλά δεν θα καταλαβαίνετε τίποτα!

- Το response παίρνει έναν επιπλέον header με το όνομα `Content-Disposition`, ο οποίος περιέχει το όνομα του αρχείου CSV. Αυτό το όνομα είναι αυθαίρετο. Μπορείτε να το ονομάσετε όπως εσείς θέλετε. Θα χρησιμοποιηθεί από τους browsers στο παράθυρο διαλόγου «Αποθήκευση ως…» κλπ.

- You can hook into the CSV-generation API by passing `response` as the first argument to `csv.writer`. The `csv.writer` function expects a file-like object, and `HttpResponse` objects fit the bill.

- For each row in your CSV file, call `writer.writerow`, passing it an iterable.

- The CSV module takes care of quoting for you, so you don’t have to worry about escaping strings with quotes or commas in them. Pass `writerow()` your raw strings, and it’ll do the right thing.

### Κάνοντας streaming σε μεγάλα αρχεία CSV

Όταν έχουμε views τα οποία παράγουν πολύ μεγάλα responses, ίσως θα θέλατε να χρησιμοποιήσετε το `StreamingHttpResponse` του Django. Για παράδειγμα, όταν κάνετε streaming ένα αρχείο το οποίο παίρνει αρκετή ώρα για να παραχθεί, μπορείτε να αποφύγετε την διακοπή σύνδεσης του load balancer (Error 522: Connection timed out) που θα προέκυπτε όσο ο server σας παράγει το response.

In this example, we make full use of Python generators to efficiently handle the assembly and transmission of a large CSV file. Rows are batched together to reduce HTTP overhead and improve compression efficiency when used with `GZipMiddleware`:

    import csv
    from itertools import batched

    from django.http import StreamingHttpResponse

    class Echo:
        """An object that implements just the write method of the file-like
        interface.
        """

        def write(self, value):
            """Write the value by returning it, instead of storing in a buffer."""
            return value

    def some_streaming_csv_view(request):
        """A view that streams a large CSV file."""
        # Generate a sequence of rows. The range is based on the maximum number of
        # rows that can be handled by a single sheet in most spreadsheet
        # applications.
        rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
        pseudo_buffer = Echo()
        writer = csv.writer(pseudo_buffer)

        def stream_batched_rows():
            for batch in batched(rows, 100):
                yield "".join(writer.writerow(row) for row in batch)

        return StreamingHttpResponse(
            stream_batched_rows(),
            content_type="text/csv",
            headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
        )

## Χρησιμοποιώντας το σύστημα template του Django

Εναλλακτικά, μπορείτε να χρησιμοποιήσετε το σύστημα template του Django για να δημιουργήσετε CSV αρχεία. Αυτή η μέθοδος είναι χαμηλού επιπέδου (low-level) εν συγκρίσει με τη χρήση του, βολικού, module `csv` της Python, αλλά παρουσιάζεται εδώ για λόγους πληρότητας.

Η ιδέα εδώ είναι να περάσετε μια λίστα από items στο template σας και να βάλετε το template να εισάγει τα κόμματα μέσα σε ένα βρόγχο επανάληψης, `for`.

Εδώ φαίνεται ένα παράδειγμα, στο οποίο παράγεται το ίδιο αρχείο CSV όπως παραπάνω:

    from django.http import HttpResponse
    from django.template import loader

    def some_view(request):
        # Create the HttpResponse object with the appropriate CSV header.
        response = HttpResponse(
            content_type="text/csv",
            headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
        )

        # The data is hardcoded here, but you could load it from a database or
        # some other source.
        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 = {"data": csv_data}
        response.write(t.render(c))
        return response

Η μόνη διαφορά αυτού του παραδείγματος με το προηγούμενο είναι ότι αυτό χρησιμοποιεί το template loading αντί του CSV module. Ο υπόλοιπος κώδικας – όπως το `content_type='text/csv'` – παραμένει ο ίδιος.

Έπειτα, δημιουργήστε ένα template `my_template_name.txt`, με τον template κώδικα, ως εξής:

    {% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
    {% endfor %}

This short template iterates over the given data and displays a line of CSV for each row. It uses the `addslashes` template filter to ensure there aren’t any problems with quotes.

## Άλλες μορφές τύπου κειμένου

Όπως είδατε, δεν υπάρχει κάτι συγκεκριμένο με το CSV εδώ – απλώς μια συγκεκριμένη μορφή εξόδου. Μπορείτε να χρησιμοποιήσετε τις ανωτέρω τεχνικές για να εξάγετε οποιαδήποτε μορφή τύπου κειμένου εσείς θέλετε. Μπορείτε, επίσης, να χρησιμοποιήσετε μια παρόμοια τεχνική για να παράγετε αυθαίρετα δυαδικά δεδομένα. Δείτε στο άρθρο εξάγοντας αρχεία PDF με το Django για ένα παράδειγμα.