CSV Exporting of Model Data

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from django.contrib.admin.options import IncorrectLookupParameters
from django.contrib.admin.views.main import ChangeList
from django.http import HttpResponse, HttpResponseForbidden, Http404
from django.core.serializers import serialize
from django.template import loader, RequestContext
from django.template.defaultfilters import slugify
from django.db.models.loading import get_model
from django.utils.encoding import smart_str
import csv

ALLOWED_EXPORT_TYPES = {
    'csv': {
        'mimetype': 'text/csv',
        'filename': '%s.csv',
        'template': 'admin/export/csv',
    },
    'json': {
        'mimetype': 'text/json',
        'filename': '%s.json',
        'serializer': 'json',
    },
    'xml': {
        'mimetype': 'text/xml',
        'filename': '%s.xml',
        'serializer': 'xml',
    },
    'yaml': {
        'mimetype': 'text/yaml',
        'filename': '%s.yaml',
        'serializer': 'yaml',
    },
    'py': {
        'mimetype': 'application/python',
        'filename': '%s.py',
        'serializer': 'python',
    }
}

def export(request, admin_site, model_name, app_label, format='csv'):
    if not request.user.is_staff:
        return HttpResponseForbidden()

    if not format in ALLOWED_EXPORT_TYPES:
        raise Http404('%s is not a supported format.' % format)

    model = get_model(app_label, model_name)
    model_admin = None

    for entry in admin_site._registry:
        if entry._meta.object_name == model._meta.object_name:
            model_admin = admin_site._registry[entry]

    if model_admin == None:
        raise Http404('ModelAdmin for model %s.%s not found' % (app_label, model_name))

    cl = ChangeList(request, model, list(model_admin.list_display), model_admin.list_display_links,
                    model_admin.list_filter, model_admin.date_hierarchy, model_admin.search_fields,
                    model_admin.list_select_related, model_admin.list_per_page, model_admin.list_editable,
                    model_admin)
    cl.formset = None

    c = RequestContext(request)
    if 'template' in ALLOWED_EXPORT_TYPES[format]:
        rows = []
        headers = []

        for field in model._meta.fields:
            headers.append(field.name)

        rows.append(headers)

        for record in cl.query_set:
            column = []

            for field in headers:
                val = getattr(record, field)

                if callable(val):
                    val = val()

                val = smart_str(val)
                column.append(val)

            rows.append(column)

        t = loader.get_template(ALLOWED_EXPORT_TYPES[format]['template'])
        c['rows'] = rows
        responseContents = t.render(c)
    elif 'serializer' in ALLOWED_EXPORT_TYPES[format]:
        responseContents = serialize(ALLOWED_EXPORT_TYPES[format]['serializer'], cl.query_set.all())
    else:
        raise Http404('Export type for %s must have value for template or serializer' % format)

    response = HttpResponse(responseContents, mimetype=ALLOWED_EXPORT_TYPES[format]['mimetype'])
    response['Content-Disposition'] = 'attachment; filename=%s' % (ALLOWED_EXPORT_TYPES[format]['filename'] % slugify(model_name))

    return response

More like this

  1. CSV Exporting of Model Data by monokrome 4 years, 5 months ago
  2. Non model specific CSV export of database content by sethtrain 6 years, 2 months ago
  3. Generic CSV export admin action factory with relationship spanning fields and labels by blackrobot 1 year, 3 months ago
  4. Generic CSV export admin action factory with labels by losttrekker 2 years, 1 month ago
  5. Generic admin action to export data into excel/csv by vinay.chittora 8 months, 2 weeks ago

Comments

Dzjim (on November 24, 2009):

Can you give an example of how to implement this code? (url pattern example)

Thx!!!

#

monokrome (on December 2, 2009):

First of all, you will need to import django.admin After you import django.admin, you can then import your view. Don't use a string name, because admin_view wont accept a string happily.

Add the following to your URL conf, and you are done:

(r'^export/(?P[HTML_REMOVED].)/(?P[HTML_REMOVED].)/(?P[HTML_REMOVED].*)/$', admin.site.admin_view(export), {'admin_site': admin.site}),

After this, create a new template in admin/export. Call this template "csv", and provide it the following code:

{% for row in rows %}{% for column in row %}{{ column|addslashes }},{%endfor%} {% endfor %}

This template is very sensitive, so make sure that all of it is on line 1 except for the last {% endfor %}, or your CSV files will be impoperly formatted.

This should be all that you need to get this snippet rolling.

Hope it helps!

#

z81 (on January 25, 2010):

Dzjim - could you post the change_list.html again - the above link is dead...

thx

#

Kludge (on March 18, 2010):

Yes, some more direction for implementing this into the admin site would be very helpful to me, e.g. what I would put into a template. thx

#

Pete (on August 9, 2011):

Could you provide the correct code - your statemetn shows

HTML_REMOVED

instead? Guess thats not intended?

(r'^export/(?P[HTML_REMOVED].)/(?P[HTML_REMOVED].)/(?P[HTML_REMOVED].*)/$', admin.site.admin_view(export), {'admin_site': admin.site}),

#

(Forgotten your password?)