[Django]-Django: export current queryset to csv by button click in browser

9👍

in your view

import csv
.....
output = []
response = HttpResponse (content_type='text/csv')
writer = csv.writer(response)
query_set = User.objects.select_related('profile').all()
#Header
writer.writerow(['First Name', 'Last Name', 'Full Name', 'Short Name'])
for user in query_set:
    output.append([user.first_name, user.last_name, user.get_full_name, user.profile.short_name])
#CSV Data
writer.writerows(output)
return response

This works prefectly

4👍

If you are using classed based views, its really easy (this is the sort of task where they shine). Subclass the main view, override the template and content type.

Here is an example from one of my projects

views.py

class SavedSamplesView(ListView):
    """
    This is the standard view returning HTML
    """
    template_name = "SavedSamples.html"
    model = Sample 
    context_object_name = "sample_list"

    def get_queryset(self) :
        slug =  self.kwargs['submission_slug']
        return Sample.objects.filter(submission__submission_slug=slug)

class SavedSamplesCsvView(SavedSamplesView):
    """
    Subclass of above view, to produce a csv file
    """
    template_name = 'SavedSamples.csv'
    content_type = 'text/csv'

The template SavedSamples.cvs looks like this (the formatting to get the newline is a little ugly, but it works). The first line is the headers, remove that if you don’t need it:

sample.id , sample.name , ... , comments
{% for sample in sample_list %}{{ sample.id }},{{ sample.name }},....,{{sample.comments}}
{% endfor %}

urls.py

url(r'^savedsamplescsv/(?P<submission_slug>[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\-_]+)/', views.SavedSamplesCsvView.as_view(),  name='saved_samples_csv'),

I would use a link instead of a button, and style it as button.

3👍

I use the following snippet to generate a CSV for my queryset. It also includes related fields, that you can choose to ignore or use something else to serialize the data. ( Such as the default serializers that come with Django )

import csv


def dump_to_csv(model, qs):
    """
    Takes in a Django queryset and spits out a CSV file.
    """

    model = qs.model
    writer = ''

    headers = []

    # Get standard fields
    for field in model._meta.get_fields():
        headers.append(field) if 'extra' not in field.name else None

    writer += ','.join([field.name for field in headers])
    writer += '\n'

    for obj in qs:
        row = []
        for field in headers:
            # Append all general fields
            if field.get_internal_type() not in ['ForeignKey', 'ManyToManyField', 'OneToOneField']:
                val = getattr(obj, field.name)
                if callable(val):
                    val = val()
                if type(val) == str:
                    val = val.encode("utf-8")
                row.append(str(val))

            # Append all fk fields
            elif field.get_internal_type() in ['ForeignKey', 'OneToOneField']:
                from django.core import serializers
                import json

                value = field.value_from_object(obj)

                if value not in [None, ""]:
                    qs = field.remote_field.model.objects.filter(pk=value)
                    json_data = serializers.serialize("json", qs, fields=(field.name for field
                                                                          in qs.first()._meta.get_fields() if
                                                                          'extra' not in field.name))
                    json_data = [o['fields'] for o in json.loads(json_data)]
                    json_data = json.dumps(json_data)
                    json_data = json_data.replace(",", ";")
                    json_data = json_data.replace("\"", "'")
                    row.append(json_data)
                else:
                    row.append("[]")

            # Append all m2m fields
            elif field.get_internal_type() in ['ManyToManyField']:
                from django.core import serializers
                import json

                qs = getattr(obj, field.name).all()
                json_data = serializers.serialize("json", qs)
                json_data = [o['fields'] for o in json.loads(json_data)]
                json_data = json.dumps(json_data)
                json_data = json_data.replace(",", ";")
                json_data = json_data.replace("\"", "'")
                row.append(json_data)

        writer += ','.join(row)
        writer += '\n'

    return writer

The reason I have this is because my use case requires me to have a JSON dump of each related object as well.

You can then return this in the response so:

file = dump_to_csv(qs.model, qs)

            response = HttpResponse(file, content_type='text/csv')
            response['Content-Disposition'] = u'attachment; filename="{0}"'.format('export.csv')
            return response

0👍

Im late, but this could help someone…
In my case, i create a submit btn in my template to post something like this:

import pandas
[...]
if request.method == 'POST':
    [...]
    dataset = "ur query here"
    response = HttpResponse (content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="file.csv"'                                
    pandas.DataFrame(dataset).to_csv(response)
    return response

Leave a comment