2010-02-01 7 views
14

У меня есть модель бронирования, которая должна проверить, доступен ли доступный предмет. Я хотел бы иметь логику определения того, доступен ли элемент централизованно, чтобы независимо от того, где я сохраняю экземпляр, этот код подтверждает, что он может быть сохранен.Показаны исключения для проверки подлинности модели на сайте администратора 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? Как я могу заставить мое исключение отображаться как любая другая ошибка проверки на сайте администратора?

ответ

9

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

+1

Я предполагаю, что я хотел написать, в одном месте, то, что обеспечивало, что экземпляр не может быть сохранен, что нарушили мои правила проверки - поскольку функция сохранения вызывается независимо от того, где вы делаете свою экономию (админ или передняя часть), имеет смысл ее поместить. –

+0

Да, но ValidationError используется для информирования конечного пользователя, что информация, которую он вводит в форму, неверна. Если вы должны заверить, что некоторые правила сохранены, возможно, вы должны использовать утверждение? Или, если сохранение может просто потерпеть неудачу, возможно, вам нужно просто получить код возврата, правильно ли он был сохранен. Я не знаю, что именно вам нужно. – gruszczy

+0

Эта ссылка не отвечает ему вообще. Он хочет повторно использовать валидацию в своей модели в админ. Не переопределить проверку в admin ... – Cerin

2

Я также попытался решить эту проблему, и есть мое решение. В моем случае мне нужно было отклонить любые изменения в связанных объектах, если 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) Metaform - вся мои 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 

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

17

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

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

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

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 файл для использования в Джанго администратора.

+1

Что делать, если 'save()' все еще вызывает исключение? – spinkus

+0

Это то, что я искал последние 3 часа! Спасибо! – kchomski

2

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

Решение, которое я нашел, должно было переопределить 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) 
+0

Чтобы заставить его работать, вам нужно импортировать: 'from django.contrib import messages' и' из django.http import HttpResponseRedirect'. –

Смежные вопросы