Отображение исключений проверки пользовательской модели на сайте администратора Django

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

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

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? Как я могу заставить свое исключение отображаться как любая другая ошибка проверки на сайте администратора?

Ответы

Ответ 1

В 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.

Ответ 2

Вот вы: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-admin Это, однако, может быть ортогонально тому, как вы это сделали. Это не должно быть ошибкой проверки, которую вы поднимаете, потому что они выражаются формами. В любом случае, посмотрите и выберите способ, который вам нравится.

Ответ 3

Я также пытался решить эту проблему, и есть мое решение. В моем случае мне нужно было отклонить любые изменения в связанных объектах, если 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) metaclass с пользовательским методом сохранения - все мои модели 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) metaform - все мои связанные с этим_файлы админов будут основаны на этом (это гарантирует, что интерфейс администратора будет информировать пользователя без ошибки интерфейса администратора):

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

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

Ответ 4

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

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

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)