我有一个预订模型需要检查预订的项目是否可用。我想知道该项目是否可以集中处理,以便无论我在何处保存实例,此代码都会验证它是否可以保存。
目前我的代码在我的模型类的自定义保存功能中:
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管理站点呢?如何让我的异常显示为管理站点中的任何其他验证错误?
答案 0 :(得分:23)
在django 1.2中,添加了模型验证。
现在,您可以向模型中添加“clean”方法,这会引发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中使用。
答案 1 :(得分:4)
相当古老的帖子,但我认为“使用自定义清洁”仍然是公认的答案。但这并不令人满意。您可以根据需要进行尽可能多的预检查,但仍然可以在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 :(得分:2)
我也尝试解决这个问题并且有我的解决方案 - 在我的情况下,如果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
在我看来,它不是那么多开销,而且仍然非常直接和可维护。
答案 3 :(得分:0)
最好的方法是将验证字段放入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]中创建的FORM
class ProductAdmin(admin.ModelAdmin):
form = FormProduct