Отображение пользовательских исключений проверки модели на сайте администратора Django - PullRequest
19 голосов
/ 01 февраля 2010

У меня есть модель бронирования, которая должна проверить, доступен ли заказываемый товар. Мне бы хотелось, чтобы логика выясняла, доступен ли элемент централизованно, чтобы независимо от того, где я сохранял экземпляр, этот код проверял, что его можно сохранить.

На данный момент у меня есть этот код в пользовательской функции сохранения класса моей модели:

def save(self):
    if self.is_available(): # my custom check availability function
        super(MyObj, self).save()
    else:
        # this is the bit I'm stuck with..
        raise forms.ValidationError('Item already booked for those dates')

Это работает нормально - ошибка возникает, если элемент недоступен, а мой элемент не сохраняется. Я могу зафиксировать исключение из кода моего внешнего интерфейса, но как насчет сайта администратора Django? Как я могу сделать так, чтобы мое исключение отображалось как любая другая ошибка проверки на сайте администратора?

Ответы [ 4 ]

23 голосов
/ 05 января 2011

В django 1.2 была добавлена ​​проверка модели.

Теперь вы можете добавить «чистый» метод в ваши модели, который вызывает исключения ValidationError, и он будет вызываться автоматически при использовании администратора django.

(В документации не очень ясно, что администратор вызывает метод clean, но я проверил его здесь)

http://docs.djangoproject.com/en/dev/ref/models/instances/?from=olddocs#validating-objects

Итак, ваш чистый метод может быть примерно таким:

from django.core.exceptions import ValidationError

class MyModel(models.Model):

    def is_available(self):
        #do check here
        return result

    def clean(self):
        if not self.is_available():
            raise ValidationError('Item already booked for those dates')

Я не использовал его широко, но похоже, что кода гораздо меньше, чем необходимость создания ModelForm, а затем ссылки на эту форму в файле admin.py для использования в django admin.

4 голосов
/ 15 сентября 2016

Довольно старый пост, но я думаю, что «использовать пользовательскую очистку» - все еще принятый ответ. Но это не удовлетворительно. Вы можете сделать столько предварительной проверки, сколько захотите, но вы все равно можете получить исключение в Model.save(), и вы можете захотеть показать сообщение пользователю способом, соответствующим ошибке проверки формы. *

Я нашел решение переопределить ModelAdmin.changeform_view () . В этом случае я ловлю ошибку целостности, сгенерированную где-то в драйвере SQL:

from django.contrib import messages
from django.http import HttpResponseRedirect

def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
    try:
        return super(MyModelAdmin, self).changeform_view(request, object_id, form_url, extra_context)
    except IntegrityError as e:
        self.message_user(request, e, level=messages.ERROR)
        return HttpResponseRedirect(form_url)
2 голосов
/ 09 февраля 2010

Я также пытался решить эту проблему, и есть мое решение - в моем случае мне нужно было отрицать любые изменения в related_objects, если main_object заблокирован для редактирования.

1) пользовательское исключение

class Error(Exception):
    """Base class for errors in this module."""
    pass

class EditNotAllowedError(Error):
    def __init__(self, msg):
        Exception.__init__(self, msg)

2) метакласс с пользовательским методом сохранения - все мои модели related_data будут основаны на этой:

class RelatedModel(models.Model):
    main_object = models.ForeignKey("Main")

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        if self.main_object.is_editable():
            super(RelatedModel, self).save(*args, **kwargs)
        else:
            raise EditNotAllowedError, "Closed for editing"

3) метаформе - все мои формы администратора related_data будут основываться на этом (это обеспечитэтот интерфейс администратора будет информировать пользователя без ошибки интерфейса администратора):

from django.forms import ModelForm, ValidationError
...
class RelatedModelForm(ModelForm):
    def clean(self):
    cleaned_data = self.cleaned_data
    if not cleaned_data.get("main_object")
        raise ValidationError("Closed for editing")
    super(RelatedModelForm, self).clean() # important- let admin do its work on data!        
    return cleaned_data

На мой взгляд, это не так много накладных расходов и все же довольно просто и легко обслуживаемо.

0 голосов
/ 26 марта 2019

Лучший способ поставить одно поле проверки - использовать ModelForm ... [forms.py]

class FormProduct(forms.ModelForm):

class Meta:
    model = Product

def clean_photo(self):
    if self.cleaned_data["photo"] is None:
        raise forms.ValidationError(u"You need set some imagem.")

И установите ФОРМУ, которую вы создаете в соответствующей модели admin [admin.py]

class ProductAdmin(admin.ModelAdmin):
     form = FormProduct
...