Wagtail is a modern open source CMS written in Python and based on Django. It is easy to integrate with existing Django projects. Apart from traditional CMS features, it provides a nice UI for managing any Django database model via the modeladmin module.
The modeladmin IndexView lists entries for a specific model in tabular form. It is easy to define which columns should be included. Starting from here, there are buttons for editing, creating and deleting entries.
One feature is missing though: Data Export
As the data is already presented in a table, CSV is an obvious export format.
This idea is not entirely original. This blog post and this StackOverflow question discuss the same thing and my code is heavily influenced by them. However, the solutions given at these sources are not quite ready to copy and paste, as they require some customization of the CSV exporting code for each model you want to export.
The code given in this blog post can be used with any Django model. Per default, all columns are exported, but this can easily be customized on a per-model basis.
I will cover the different implementation parts in detail. If you just want to copy-paste and get on with your life, that’s fine too. Just make sure you copy all the given code snippets. It is fine to put everything into
wagtail_hooks.py, except the HTML template.
The first thing you need whenever you want to add custom functionality to Wagtail’s modeladmin is usually a
Most of this code is just to get the CSS classes for the button right. The CSS classes
icon-download will ensure a simple button with a download icon and some text.
Next, we need an AdminURLHelper that helps with generation, naming, and referencing of our new
Once again, this looks a little more complicated than it is. We just need to add the
export action to the
non_object_specific_actions, because Wagtail treats actions as object-specific per default and will attempt to add the an object’s PK to the URL. Additionally, the URL helper appends the modeladmin filters to the action so that only the filtered data is exported.
Finally, we need an
ExportView that implements the CSV export. For this, we will use some help from
pip install django-queryset-csv
Using this, our view is very simple:
It is worth to note the
model_admin field. We will use this for specifying a custom list of exported fields. Lines 5 and 6 make sure that whenever
model_admin is set and the
csv_export_fields attribute is given, the custom field list is used instead of the default behavior that just exports all fields.
Making use of Python’s Multiple-Inheritance system, we can create a Mixin that we will later use to override
get_admin_urls_for_registration all at once:
Now, we need to create an HTML template that includes our new button plus the original modeladmin buttons:
Enabling CSV Export for Models
To make a modeladmin table exportable, just add the mixin to your ModelAdmin definitions in
wagtail_hooks.py and set the
class FooModelAdmin(ExportModelAdminMixin, ModelAdmin): index_template_name = "wagtailadmin/export_csv.html"
If you want to customize the CSV columns, you can use our new optionl
csv_export_fields attribute. It even allows to export attributes of related tables using regular Django ORM syntax (
class FooModelAdmin(ExportModelAdminMixin, ModelAdmin): index_template_name = "wagtailadmin/export_admin.html" csv_export_fields = [ 'bar', 'foobar', 'other_model__attribute' ]
In 2020, Wagtail is almost certainly the best option to add CMS functionality to a Django project. This post illustrates its extensibility. In a couple of minutes, you can enable CSV export for all your Django models.