Существует ли метод ModelAdmin, который запускается после Model.clean()?
У меня возникает ошибка ValidationError в методе clean() моей модели
from django.core.exceptions import ValidationError
class PosDetail(models.Model, PosDetailChecksMixin):
self._errors = set()
...
def clean(self, *args, **kwargs):
if PosDetail.objects.filter(username=self.username).exists(): # example ValidationError
self._errors.add('check_duplicates')
raise ValidationError("This username is already in use.", code="invalid")
return super().clean(*args, **kwargs)
После этого в форме просмотра изменений администратора после POST-запроса отображается ошибка ValidationError.
я хочу показать кнопку в админке для изменения вида после отправки формы
я попробовал метод save_model, но он не выполняется, если возникает ошибка ValidationError. Я также пытался переопределить метод change_view в ModelAdmin, но он выполняется до метода Model clean, поэтому пропускает валидацию.
@admin.register(PosDetail)
class BddDetailAdmin(admin.ModelAdmin):
...
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
pos_detail = self.get_object(request, object_id)
if request.POST:
if pos_detail and 'check_duplicates' in pos_detail._errors:
extra_context['show_save_anyway'] = True
else:
extra_context['show_save_anyway'] = False
return super().change_view(request, object_id, form_url, extra_context)
Существует ли метод ModelAdmin, который запускается после Model.clean(), чтобы я мог перехватить ошибку ValidationError, которая возникает в методе Model.clean.
Для этого следует использовать типовые формы.
К ошибкам формы будут добавлены все ошибки валидации, возникающие при проверке формы. Для форм моделей это включает ошибки, возникающие при проверке модели. Смотрите:
Чтобы связать ошибку с полем, оберните "оригинальную" ValidationError в другую ValidationError:
class PosDetail(models.Model, PosDetailChecksMixin):
def clean(self, *args, **kwargs):
if PosDetail.objects.filter(username=self.username).exists():
raise ValidationError(
{"username": ValidationError("This username is already in use.", code="duplicate")}
)
return super().clean(*args, **kwargs)
Форма с "дублирующимися" данными будет помечена как недействительная:
PosDetail.objects.create(username="foo")
PosDetailForm = modelform_factory(PosDetail, fields=["username"])
form = PosDetailForm(data={"username": "foo"})
print(f"{form.is_valid()=}, {repr(form.errors)}")
>>> form.is_valid()=False, {"username": "This username is already in use."}
В админке вы можете сделать примерно следующее:
class BddDetailAdmin(admin.ModelAdmin):
def change_view(self, request, object_id, form_url="", extra_context=None):
response = super().change_view(request, object_id, form_url, extra_context)
if response.context_data["adminform"].form.has_error("username", code="duplicate"):
response.context_data["show_save_anyway"] = True
return response