Skip to content

Instantly share code, notes, and snippets.

@mgerring
Created September 5, 2012 22:04
Show Gist options
  • Save mgerring/3645889 to your computer and use it in GitHub Desktop.
Save mgerring/3645889 to your computer and use it in GitHub Desktop.
"Export to CSV" action for django admin
import unicodecsv
from django.http import HttpResponse
def export_as_csv_action(description="Export selected objects as CSV file",
fields=None, exclude=None, header=True):
"""
This function returns an export csv action
'fields' and 'exclude' work like in django ModelForm
'header' is whether or not to output the column names as the first row
"""
def export_as_csv(modeladmin, request, queryset):
opts = modeladmin.model._meta
if not fields:
field_names = [field.name for field in opts.fields]
else:
field_names = fields
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=%s.csv' % unicode(opts).replace('.', '_')
writer = unicodecsv.writer(response, encoding='utf-8')
if header:
writer.writerow(field_names)
for obj in queryset:
row = [getattr(obj, field)() if callable(getattr(obj, field)) else getattr(obj, field) for field in field_names]
writer.writerow(row)
return response
export_as_csv.short_description = description
return export_as_csv
from django.contrib import admin
from repsf.map.models import Location
from django.http import HttpResponse, HttpResponseForbidden
from actions import export_as_csv_action
class SpamAdmin(admin.ModelAdmin):
list_display = ['wink','nudge']
actions = [export_as_csv_action("CSV Export", fields=['wink','nudge'])]
admin.site.register(Location, LocationAdmin)
@chan24092005
Copy link

in newer version of python and httpResponse, it should be

        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename=%s.csv' % str(opts).replace('.', '_')

@JamieRobertson
Copy link

This is great. Does the exclude argument do anything though?

@JamieRobertson
Copy link

JamieRobertson commented Jul 31, 2018

Could the exclude argument be used like this?

if not fields:
    field_names = [field.name for field in meta.fields]
else:
    field_names = fields

if exclude:
    exclude_names = exclude.split() if isinstance(exclude, str) else exclude  # exclude could be a string
    field_names = [x for x in field_names if x not in list(exclude_names)]

Here exclude could be passed in as a list, a tuple, or a string.

@JamieRobertson
Copy link

JamieRobertson commented Jul 31, 2018

*Corrected an error - must assign exclude to a new variable 'exclude_names', or local variable referenced before assignment error will be thrown

@dfranc3373
Copy link

Amazing job on this one

@hlodver
Copy link

hlodver commented Sep 25, 2018

Sometimes it can be useful to follow foreign keys If that is what you need you can use:

def rgetattr(obj, attr, *args):
    def _getattr(obj, attr):
        return getattr(obj, attr, *args)
    return functools.reduce(_getattr, [obj] + attr.split('__'))

Just import functools and be careful not to go too deep Django docs for the QuerySet API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment