Как то раз у меня возникла задача добавить возможность комплексного внесения данных в БД, для этого требуется заполнить несколько полей относящихся к разным объектам, но добавить ее нужно в одной транзакции. Конечно можно написать такой код для фронтенда, но, а если нужно именно в “админке”.
Первый вариант предлагал просто добавить недостающие поле в наследник AdminModel, однако с этим методом, который работал в старых версиях до 3.х возникли проблемы, так как валидация Django находила факт отсутствия поля в модели данных.
На самом деле под формой я подразумеваю, комплекс из контроллеров (url) и отображений, решающий задачи просмотре и редактирования данных. Для моей задачи нужна форма для добавления данных.
Долго поискав в интернете я нашел несколько вариантов решения проблемы:
Вариант 1 создание формы на основе “виртуальной” моделе данных.
Метод был найден в репозитории “idlesign/django-etc” на гите суть его заключается в создании абстрактной модели данных в которой описываются необходимые поля, а потом специализированным класом наследником AdminModel, регистрируется в admin.site:
Код здесь привожу с небольшими изменениями:
Класс EtcAdmin, это сущность позволяющая выводить сообщения в админ интерфейс (так как форма замкнута сама на себя, то требуется уведомить пользователя об успешности операции). Класс ReadonlyAdmin создает форму доступную только для просмотра данных (все метода редактирования заблокированы), вполне может пригодится и в других проектах ;). Самое интересное сосредоточено в двух последних класах. Класс CustomPageModelAdmin – это класс админ формы для добавления данных, он создает метод view_custom, который регистрирует как контроллер для редактирования и переопределяет метод save_model, отвечающий за сохранения модели, делегируя сохранения модели. И последний класс CustomModelPage,наследники которого и будут описывать форму с требуемыми полями, а все операции по обработки данных осуществляются в методе save.
Огромный плюс этого метода заключается в том, что он позволяет использовать всю мощь админ интерфейса. Единственный минус, это невозможность зарегистрировать форму через admin.site.register. Регистрация всегда осуществляется через вызов register класса CustomModelPage или его наследника.
Например, пускай есть некая модель в базе Model1 и необходима форма, тогда возможна даже такая функциональность:
Тут в примере StandartModel1Admin это стандартная функциональность администрирования модели, в SomeCustomAdminForm(CustomPageModelAdmin):которой определены поля для поиска и сортировки. SomeCustomAbsractModel – это наша специальная форма в которой есть необходимые поля, вализация полей производится в методе clean, а сохранение в save. Класс SomeCustomAdminForm это наследник CustomPageModelAdmin, в котором используется стандартная настройка интерфейса администрирования, например определена возможность autocomplete_fields, поиск для моделей ManyToOne и ManyToMany.
Метод 2. Переопределения методов get_fieldsets или get_fields
Этот метод взят с сайта stackoverflow.com и вот тут и немного доработан
Например создав такой миксин можно добавлять поля в формы:
Пример использования:
Вся сложность данного метода в требовании достаточно сложного определения dynamic_fieldsets или dynamic_fields. Вся полезная работа делается в методе save_model.
Метод 3. Добавлене полей только для чтения
Этот метод подойдет для случаев когда просто в таблицу для вывода требуется добавить какие то данные для отображения. Я нашел его на сайте xxx-cook-book.gitbooks.io.
Это довольно простой метод который требует определения некоторого метода для формирования отображения и внесения его в список полей только для чтения (readonly_fields)