Package: django-data-exports
Author: Mathieu Agopian andcontributorsLicence: BSDCompatibility: Python 2.6, Python 2.7, Python 3.3, Python 3.4, Django 1.3+ (class-based-views required)Requirements: django-inspect-modelProject URL:https://github.com/magopian/django-data-exports/Documentation:http://django-data-exports.readthedocs.org/en/latest/Django-data-exports is a model data exports app for Django. It allows you to easily
create exports for your models.Adding this app to your project will let you create exports for your models,
and customize the data that will be exported by specifying which columns to include,
and which format to use.Typical use case: display a few columns from one of your models as a HTML table to
be easily copy/pasted to a spreadsheet.Installationpip install django-data-exportsThen add to your project’sINSTALLED_APPS. Insettings.py:INSTALLED_APPS = (
    '...',
    # whatever you already have
    '...',
    'data_exports',
)Install the models:./manage.py syncdb  # or ./manage.py migrate if you're using southAnd finally, plug the urls to yourROOT_URLCONF:urlpatterns = patterns(
    '',
    # ... all the other urls you already have

    # exports
    url(r'^exports/', include('data_exports.urls', namespace='data_exports')),
)UsageEither add exports through the admin, or use the included example views.
If there’s no export format attached to an export, thedata_exports/export_detail.htmltemplate will be rendered with the following context:export: the export itselfdata: a queryset of all theexport.model’s instanceUsing the adminThere’s nothing specific to do here: connect to the admin, and add new exports. A few things to note:when you create an export, it’s not possible to add columns at first. The reason being that the model is needed to be able to populate the column nameswhen you add an export, clicking on the “save” button will have the same effect as clicking on “save and continue editing”once an export is created, and is being edited, the columns can be added (and are displayed as inlines)Using the included example viewsThere’s three included example views:/exports/add: create a new export/exports/<exportslug>/columns: add columns to your export/exports/<exportslug>: visualize your exportThere is, at the moment, no example view for the export formats.Export columnsColumn choices make use ofdjango-inspect-modelto build the list of accessible “items”. Please check this app’s documentation to know more about “items”.Choices are built bydata_exports.forms.get_choices, and will consist of all the accessible items on the exported model, and on all its related models. The only related fields accessible are those on models that are directly related, using forward or reverse OneToOne fields and forward ForeignKey fields.Example:class Foo(models.Model):
    name = CharField(max_length=50)
    bar = ForeignKey(Bar)

class Bar(models.Model):
    name = CharField(max_length=50)An export ofFoowill have the following column choices:name: Foo.namebar: Foo.bar, which is unicode(Foo.bar)bar.name: Bar.nameTo display the value of those columns, the included templates usedata_exports.templatetags.getter_tags:Getattribute filter{% load getter_tags %}
{{ obj|getattribute:column }}This is roughly equivalent to thegetattrpython builtin, but can cope with column choices:ifcolumndoesn’t have a dot, returngetattr(obj, column), orgetattr(obj,column)()if it’s a callableifcolumndoes have a dots (eg:bar.name), recursively callgetattribute()to get to the final attribute:attr = getattribute(obj, 'bar.name')
# equivalent to:
temp = getattr(obj, 'bar')
attr = getattr(temp, 'name')Nice_display filter{% load getter_tags %}
{{ obj|getattribute:column|nice_display }}For now, all this does is return a comma-separated list of related instances for a many-to-many field.If theitemfield has anallmethod:return ', '.join(map(unicode, item.all()))Advanced usageExport formatsExports can export to a given format:class Format(models.Model):
    name = models.CharField(max_length=50)
    file_ext = models.CharField( max_length=10, blank=True)
    mime = models.CharField(max_length=50)
    template = models.CharField(max_length=255)Themimefield is theContent-Typeneeded for the response.file_extwill be used to compute the export’s filename, provided viaContent-Dispositionheader.Example: let’s take a naive export to csv:mime: text/csvfile_ext: csvname: Naive CSV formattemplate:data_exports/export_detail_csv.html(included as an example)If an export uses this format, visiting the export’s view page/exports/<exportslug>will offer a file download, named<exportslug>.csv.Filtering exportsTo restrict entries access, you can use a class method or a static methodexport_querysetwhich will get the request object
and returns the queryset of items to display.from django.contrib.auth.models import User
from django.db import models

class Client(models.Model):
    name = models.CharField(max_length=63)
    users = models.ManyToManyField(User)


class ClientData(models.Model):
    client = models.ForeignKey('Client')
    address = models.CharField(max_length=255)
    money_hidden_in_the_garden = models.IntegerField()

    @classmethod
    def export_queryset(cls, request):
        qs = cls.objects.all()
        if not request.user.is_superuser:
            qs = qs.filter(client__in=request.user.client_set.all())
        return qsUsing your own viewsTo use your own views, you need to use the same url names as indata_exports/urls.py, and make sure they use thedata_exportsnamespace, asdjango.core.urlresolvers.reverseis used internally to compute the needed urls.You can check the included example views indata_exports/views.py, and of course reuse the forms provided indata_exports/forms.py.Decorating the included viewsSay you need to decorate the export view with thestaff_member_requireddecorator:url(r'^export/(?P<slug>[^/]+)/?$',
    staff_member_required(export_view),
    name='export_view'),You still need to include this new url using a namespace, or the calls toreversein the views won’t work. This is a way to do it (taken from theDjango documentation:from django.conf.urls import include, patterns, url

data_exports_patterns = patterns('',
    url(r'^export/(?P<slug>[^/]+)/?$',
        staff_member_required(export_view),
        name='export_view'),
)

url(r'^exports', include(data_exports_patterns, namespace='data_exports')),Using your own templatesDjango-data-exportsmakes use of Django’s template overloading mechanism. This means that if you provide adata_exports/export_detail.htmltemplate which has precedence over the one bundled with the app, it’ll be used.Example: say you have atemplates/folder in your project, and the appropriateTEMPLATE_DIRSsetting. Place your own template inproject/templates/data_exports/export_detail.htmlto have it used instead of the template bundled with the app indata_exports/templates/data_exports/export_detail.html.There’s three included templates:data_exports/base.html: extended by the two other templatesdata_exports/export_detail.html: used by default for exports that don’t specify a formatdata_exports/export_detail_csv.html: used by the “naive csv format” detailed inExport formats.HackingSetup your environment:git clone https://github.com/magopian/django-data-exports.git
cd django-data-exportHack and run the tests usingToxto test
on all the supported python and Django versions:make testTo build the docs:make docs