kei*_*rth 7 python django postgresql
背景:我的Django应用程序位于预先存在的Postgresql数据库之上.该数据库具有非常复杂的触发器和约束网络.
问题:在Django Admin中,如果用户在保存时导致DatabaseError,我想以用户友好的格式向他们显示错误,类似于builtin forms.ValidationError.
示例(这不起作用,导致500)
def save_model(self, request, obj, form, change):
try:
obj.save()
except DatabaseError as e:
raise forms.ValidationError(e)
Run Code Online (Sandbox Code Playgroud)
预期结果:
在Admin中显示给用户," Database Error: ID 58574 - Price is outside customers requested range. Cannot add or update a child row: a foreign key constraint fails."
如果可能,您需要略微更改逻辑.你需要的是定制AdminModel.form.所有验证都应该在那里进行.请参阅说明save_model():
ModelAdmin.save_model()和ModelAdmin.delete_model()必须保存/删除对象,它们不是用于否决目的,而是允许您执行额外的操作.
但是,如果你的情况是这样,你不能做表格内的所有验证我会继承ModelAdmin和覆盖def add_view(),def change_view()并def changelist_view()像这样:
from django.contrib import admin
from django import forms
from django.contrib.admin import helpers
from django.contrib.admin.options import csrf_protect_m, IS_POPUP_VAR
from django.utils.translation import ugettext as _
from django.utils.encoding import force_text
# for nonfield errors to show correctly
from django.forms.forms import NON_FIELD_ERRORS
from .models import TestModel
class TestModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
raise Exception('test exception')
@csrf_protect_m
def add_view(self, request, form_url='', extra_context=None):
try:
return super(TestModelAdmin, self).add_view(request, form_url, extra_context)
except Exception as e:
pass
# mimic parent class on error
model = self.model
opts = model._meta
ModelForm = self.get_form(request)
formsets = []
inline_instances = self.get_inline_instances(request, None)
form = ModelForm(request.POST, request.FILES)
form.is_valid()
# make faked nonfield error
# see http://stackoverflow.com/questions/8598247/how-to-append-error-message-to-form-non-field-errors-in-django
form._errors[NON_FIELD_ERRORS] = form.error_class([e.message])
# We may handle exception here (just to save indentation)
adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
self.get_prepopulated_fields(request),
self.get_readonly_fields(request),
model_admin=self)
media = self.media + adminForm.media
inline_admin_formsets = []
for inline, formset in zip(inline_instances, formsets):
fieldsets = list(inline.get_fieldsets(request))
readonly = list(inline.get_readonly_fields(request))
prepopulated = dict(inline.get_prepopulated_fields(request))
inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
fieldsets, prepopulated, readonly, model_admin=self)
inline_admin_formsets.append(inline_admin_formset)
media = media + inline_admin_formset.media
context = {
'title': _('Add %s') % force_text(opts.verbose_name),
'adminform': adminForm,
'is_popup': IS_POPUP_VAR in request.REQUEST,
'media': media,
'inline_admin_formsets': inline_admin_formsets,
'errors': helpers.AdminErrorList(form, formsets),
'app_label': opts.app_label,
'preserved_filters': self.get_preserved_filters(request),
}
context.update(extra_context or {})
return self.render_change_form(request, context, form_url=form_url, add=True)
admin.site.register(TestModel, TestModelAdmin)
Run Code Online (Sandbox Code Playgroud)
我的models.py:
from django.db import models
class TestModel(models.Model):
text = models.TextField()
Run Code Online (Sandbox Code Playgroud)
你看,内部没有简单的方法,save_model()所以你必须复制粘贴部分表格准备代码.
@twil-感谢您的帮助。你让我走上了正轨。非常感谢您的帮助。但是,该解决方案并非开箱即用。在我的测试用例中并没有显示错误,也没有使用change_view。我想和我一起工作。
from django.contrib.admin import ModelAdmin
from django.db import DatabaseError, IntegrityError
from django.contrib import messages
class ShowValidationAdmin(ModelAdmin):
def add_view(self, request, form_url='', extra_context=None):
try:
return super(ShowValidationAdmin, self).add_view(request, form_url, extra_context)
except (IntegrityError, DatabaseError) as e:
request.method = 'GET'
messages.error(request, e.message)
return super(ShowValidationAdmin, self).add_view(request, form_url, extra_context)
def change_view(self, request, object_id, form_url='', extra_context=None):
try:
return super(ShowValidationAdmin, self).change_view(request, object_id, form_url, extra_context)
except (IntegrityError, DatabaseError) as e:
request.method = 'GET'
messages.error(request, e.message)
return super(ShowValidationAdmin, self).change_view(request, object_id, form_url, extra_context)
Run Code Online (Sandbox Code Playgroud)
注意:该版本似乎也可以跨版本使用(django 1.3-1.6)。让我知道是否有人有更好的方法。我将等奖赏。
| 归档时间: |
|
| 查看次数: |
2677 次 |
| 最近记录: |