I'm trying to add a model resource from django-import-export into the admin for Wagtail. The only documentation I can find says that you would do it through hooks. The problem is, I keep getting the error:
missing 2 required positional arguments: 'model' and 'admin_site'
The whole resource
and ModelAdmin
are:
class AccountResource(resources.ModelResource):
class Meta:
model = Account
fields = ('first_name', 'last_name', 'email', 'created', 'archived')
class AccountsAdmin(ImportExportModelAdmin, ModelAdmin):
resource_class = AccountResource
model = Account
menu_label = 'Accounts' # ditch this to use verbose_name_plural from model
menu_icon = 'group' # change as required
menu_order = 200 # will put in 3rd place (000 being 1st, 100 2nd)
add_to_settings_menu = False # or True to add your model to the Settings sub-menu
exclude_from_explorer = False # or True to exclude pages of this type from Wagtail's explorer view
list_display = ('first_name', 'last_name', 'email', 'created', 'archived')
search_fields = ('first_name', 'last_name', 'email', 'created')
# Now you just need to register your customised ModelAdmin class with Wagtail
modeladmin_register(AccountsAdmin)
Any suggestions?
The Wagtail ModelAdmin
does not share the API of the Django ModelAdmin
.
The mixins from django-import-export expect to be used with a Django ModelAdmin
and won't work with Wagtail ModelAdmin
as you have experienced yourself.
For the export functionality, I have solved the problem by hooking the export_action
of a Django ModelAdmin
with the ExportMixin
into the urls of a Wagtail ModelAdmin
.
This might not be too pretty, but allows reusing the view and the logic that is part of the ExportMixin
.
I have published an example Project on GitHub that makes use of this design.
The actual glue code that can be found here is not all that much:
from django.conf.urls import url
from django.contrib.admin import ModelAdmin as DjangoModelAdmin
from django.core.exceptions import ImproperlyConfigured
from django.utils.http import urlencode
from django.utils.translation import gettext_lazy as _
from import_export.admin import ExportMixin
from wagtail.contrib.modeladmin.helpers import ButtonHelper
class ExporterDummySite:
name = None
def each_context(self, request):
return {}
class WMAExporter(ExportMixin, DjangoModelAdmin):
export_template_name = 'wma_export/export.html'
def __init__(self, wagtail_model_admin):
self.wagtail_model_admin = wagtail_model_admin
super().__init__(wagtail_model_admin.model, ExporterDummySite())
def get_export_queryset(self, request):
index_view = self.wagtail_model_admin.index_view_class(
model_admin=self.wagtail_model_admin
)
index_view.dispatch(request)
return index_view.get_queryset(request)
class ExportButtonHelper(ButtonHelper):
export_button_classnames = ['bicolor', 'icon', 'icon-download']
def export_button(self, classnames_add=None, classnames_exclude=None):
if classnames_add is None:
classnames_add = []
if classnames_exclude is None:
classnames_exclude = []
classnames = self.export_button_classnames + classnames_add
cn = self.finalise_classname(classnames, classnames_exclude)
return {
'url': self.url_helper.get_action_url("export") + '?' + urlencode(self.view.params),
'label': _('Export'),
'classname': cn,
'title': _('Export these %s') % self.verbose_name_plural,
}
class WMAExportMixin:
button_helper_class = ExportButtonHelper
exporter_class = None
def get_admin_urls_for_registration(self):
return super().get_admin_urls_for_registration() + (
url(self.url_helper._get_action_url_pattern("export"),
self.export_view,
name=self.url_helper.get_action_url_name("export")),
)
def export_view(self, request):
if self.exporter_class is None:
raise ImproperlyConfigured(f"{self.__class__.__name__}.exporter_class not set!")
exporter = self.exporter_class(self)
return exporter.export_action(request)
I would assume that something similar can be done to implement the import part.