Add CSV Export to Wagtail's Modeladmin
- Why Keyboard Shortcuts don't work on non-US Layouts and how Devs could fix it
- An Interactive Virtual Keyboard to Visualize any Collection of Shortcuts
- An app to show the shortcuts of the current application for Windows, Linux, and macOS
- Automatically add <kbd>-tags with a Single Regex
Introduction
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.
Implementation
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.
ButtonHelper
The first thing you need whenever you want to add custom functionality to Wagtail’s modeladmin is usually a ButtonHelper
:
|
|
Most of this code is just to get the CSS classes for the button right. The CSS classes icon
and icon-download
will ensure a simple button with a download icon and some text.
AdminURLHelper
Next, we need an AdminURLHelper that helps with generation, naming, and referencing of our new export
URL:
|
|
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.
ExportView
Finally, we need an ExportView
that implements the CSV export. For this, we will use some help from django-queryset-csv
.
Install via
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.
Mixin
Making use of Python’s Multiple-Inheritance system, we can create a Mixin that we will later use to override button_helper_class
, url_helper_class
, export_view_class
and get_admin_urls_for_registration
all at once:
|
|
HTML Template
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 index_template_name
:
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'
]
Conclusion
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.