Пользовательский декоратор для Django admin.ModelAdmin для добавления действий
Я пытаюсь создать функцию "экспорт модели в csv в панели администратора" и добавить ее к actions
в admin.ModelAdmin. Выбрав несколько строк в таблице в панели администратора, цель состоит в том, чтобы экспортировать выбранные строки в csv. Однако мой текущий код в decorators.py::exportable_model
не достиг моей цели.
Версии:
- Python: 3.10
- Django: 4.0.4
mixins.py
import csv
import codecs
from django.http import HttpResponse
class ExportCsvMixin:
# ref: https://books.agiliq.com/projects/django-admin-cookbook/en/latest/export.html
def export_as_csv(self, request, queryset):
meta = self.model._meta
field_names = [field.name for field in meta.fields]
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta)
# To export CN characters. Ref: https://stackoverflow.com/a/63242835/16450509
response.write(codecs.BOM_UTF8)
writer = csv.writer(response)
writer.writerow(field_names)
for obj in queryset:
row = writer.writerow([getattr(obj, field) for field in field_names])
return response
export_as_csv.short_description = "Export Selected (.csv)"
admin.py
@exportable_model(export_format="csv")
@admin.register(ParticipantType)
class ParticipantTypeAdmin(admin.ModelAdmin, ExportCsvMixin):
list_display = [field.name for field in ParticipantType._meta.get_fields()]
@exportable_model(export_format="csv")
@admin.register(PropsEventType)
class PropsEventTypeAdmin(admin.ModelAdmin, ExportCsvMixin):
list_display = [field.name for field in PropsEventType._meta.get_fields()]
@exportable_model(export_format="csv")
@admin.register(LimitedTimeEventType)
class LimitedTimeEventTypeAdmin(admin.ModelAdmin, ExportCsvMixin):
list_display = [field.name for field in LimitedTimeEventType._meta.get_fields()]
Тенденция decorators.py
, которая ссылается на стиль кодирования в register
функции в @admin.register
(from django.contrib import admin):
def exportable_model(export_format: str):
from django.contrib.admin import ModelAdmin
from .mixins import ExportCsvMixin
def _decorator(admin_class):
if not issubclass(admin_class, ModelAdmin):
raise ValueError("Wrapped class must subclass ModelAdmin.")
actions = admin_class.actions
if export_format == "csv" and issubclass(admin_class, ExportCsvMixin):
# I tried to append the action instead of overwriting the existing actions,
# but this code gives me errors.
actions.append("export_as_csv")
admin_class.actions = actions
return admin_class
return _decorator
Когда я запускаю Django с помощью python manage.py runserver
, приложение выдает следующие ошибки:
Exception in thread django-main-thread:
Traceback (most recent call last):
File "C:\Program Files\Python310\lib\threading.py", line 1009, in _bootstrap_inner
self.run()
File "C:\Program Files\Python310\lib\threading.py", line 946, in run
self._target(*self._args, **self._kwargs)
File "C:\Projects\py\kab-event-calendar-py\venv\lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
fn(*args, **kwargs)
File "C:\Projects\py\kab-event-calendar-py\venv\lib\site-packages\django\core\management\commands\runserver.py", line 134, in inner_run
self.check(display_num_errors=True)
File "C:\Projects\py\kab-event-calendar-py\venv\lib\site-packages\django\core\management\base.py", line 558, in check
raise SystemCheckError(msg)
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:
ERRORS:
<class 'enums.admin.LimitedTimeEventTypeAdmin'>: (admin.E130) __name__ attributes of actions defined in LimitedTimeEventTypeAdmin must be unique. Name 'export_as_csv' is not unique.
<class 'enums.admin.ParticipantTypeAdmin'>: (admin.E130) __name__ attributes of actions defined in ParticipantTypeAdmin must be unique. Name 'export_as_csv' is not unique.
<class 'enums.admin.PropsEventTypeAdmin'>: (admin.E130) __name__ attributes of actions defined in PropsEventTypeAdmin must be unique. Name 'export_as_csv' is not unique.
System check identified 3 issues (0 silenced).
Если я правильно понимаю, эта ошибка выглядит так, как будто декорированные подклассы admin.ModelAdmin повторно используют actions
в классах-сестрах, что-то вроде
@admin.register(ParticipantType)
class ParticipantTypeAdmin(admin.ModelAdmin, ExportCsvMixin):
list_display = [field.name for field in ParticipantType._meta.get_fields()]
actions = ["export_as_csv"]
@admin.register(PropsEventType)
class PropsEventTypeAdmin(admin.ModelAdmin, ExportCsvMixin):
list_display = [field.name for field in PropsEventType._meta.get_fields()]
actions = ["export_as_csv", "export_as_csv"]
@admin.register(LimitedTimeEventType)
class LimitedTimeEventTypeAdmin(admin.ModelAdmin, ExportCsvMixin):
list_display = [field.name for field in LimitedTimeEventType._meta.get_fields()]
actions = ["export_as_csv", "export_as_csv", "export_as_csv"]
Как исправить функцию exportable_model
?