Login

Generic CSV export admin action factory with relationship spanning fields and labels

Author:
blackrobot
Posted:
December 21, 2012
Language:
Python
Version:
1.4
Score:
2 (after 2 ratings)

Based on #2712

"This snippet creates a simple generic export to csv action that you can specify the fields you want exported and the labels used in the header row for each field. It expands on #2020 by using list comprehensions instead of sets so that you also control the order of the fields as well."

The additions here allow you to span foreign keys in the list of field names, and you can also reference callables.

 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
import csv
from django.http import HttpResponse
 
 
def prep_field(obj, field):
    """ Returns the field as a unicode string. If the field is a callable, it
    attempts to call it first, without arguments.
    """
    if '__' in field:
        bits = field.split('__')
        field = bits.pop()
 
        for bit in bits:
            obj = getattr(obj, bit, None)
 
            if obj is None:
                return ""
 
    attr = getattr(obj, field)
    output = attr() if callable(attr) else attr
    return unicode(output).encode('utf-8') if output else ""
 
 
def export_csv_action(description="Export as CSV", fields=None, exclude=None, header=True):
    """ This function returns an export csv action. """
    def export_as_csv(modeladmin, request, queryset):
        """ Generic csv export admin action.
        Based on http://djangosnippets.org/snippets/2712/
        """
        opts = modeladmin.model._meta
        field_names = [field.name for field in opts.fields]
        labels = []
 
        if exclude:
            field_names = [f for f in field_names if f not in exclude]
 
        elif fields:
            field_names = [field for field, _ in fields]
            labels = [label for _, label in fields]
 
        response = HttpResponse(mimetype='text/csv')
        response['Content-Disposition'] = 'attachment; filename=%s.csv' % (
                unicode(opts).replace('.', '_')
            )
 
        writer = csv.writer(response)
 
        if header:
            writer.writerow(labels if labels else field_names)
 
        for obj in queryset:
            writer.writerow([prep_field(obj, field) for field in field_names])
        return response
    export_as_csv.short_description = description
    return export_as_csv


## Example Usage

from django.contrib import admin

 
class ExampleModelAdmin(admin.ModelAdmin):
    raw_id_fields = ('field1',)
    list_display = ('field1', 'field2', 'field3',)
    actions = [
        export_csv_action("Export Sepecial Report",
            fields=[
                ('field1', 'label1'),
                ('foreign_key1__foreign_key2__name', 'label2'),
                ('field3', 'label3'),
            ],
            header=True
        ),
    ]
 
admin.site.register(ExampleMode, ExampleModelAdmin)

More like this

  1. codigo alto nivel by MrRocklion 4 weeks ago
  2. Load template from specific app by Krzysiek555 1 month, 2 weeks ago
  3. PostgreSQL JSON subqueries by dolamroth 1 month, 3 weeks ago
  4. "Magic Link" Management Command by webology 6 months, 3 weeks ago
  5. Closest ORM models to a latitude/longitude point by simonw 6 months, 3 weeks ago

Comments

selimnairb (on February 1, 2014):

Thanks. I've extended this to add support for writing all entries of many-to-many relationships as strings separated by a secondary delimiter. See here

#

Please login first before commenting.