首页 文章

在Django管理站点中显示自定义模型验证异常

提问于
浏览
18

我有一个预订模型,需要检查预订的项目是否可用 . 我想知道这个项目是否可以集中存在的逻辑,这样无论我在哪里保存实例,这个代码都会验证它是否可以保存 .

目前我在我的模型类的自定义保存功能中有这个代码:

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 回答

  • 21

    在django 1.2中,添加了模型验证 .

    您现在可以向模型添加“干净”方法,这会引发ValidationError异常,并且在使用django admin时会自动调用它 .

    (在文档中不太清楚管理员调用了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

    在这里你去:http://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-admin然而,这可能与你采取的方式正交 . 这不应该是验证错误,因为这些是由表单引发的 . 无论如何,看看并选择你喜欢的方式 .

  • 2

    很老的帖子,但我认为"use custom cleaning"仍然是公认的答案 . 但这并不令人满意 . 您可以根据需要进行尽可能多的预检查,但仍可能在 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)
    
  • 9

    我也尝试解决这个问题并且有我的解决方案 - 在我的情况下,如果main_object被锁定以进行编辑,我需要拒绝related_objects中的任何更改 .

    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
    

    在我看来,它不是那么多开销,而且仍然非常直接和可维护 .

相关问题