假设我有一个简单的Django模型:
class MyModel(Model):
created = models.DateTimeField(default=datetime.utcnow)
@property
def my_property(self):
raise ValueError('Is anyone there')
然后在管理GUI中,将my_property
显示为只读字段。
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
...
readonly_fields = ['my_property']
令我惊讶的是,如果在Django管理GUI中生成值时引发任何异常,则Django将抑制该错误,并仅将“-”显示为值。
我花了一些时间才意识到是这种情况。
有没有一种方法可以在发生异常时强制Django显示异常?
答案 0 :(得分:0)
这是因为 AdminReadOnlyField 的实现:
field, obj, model_admin = self.field['field'], self.form.instance, self.model_admin
try:
f, attr, value = lookup_field(field, obj, model_admin)
except (AttributeError, ValueError, ObjectDoesNotExist):
result_repr = self.empty_value_display
所以它会默默地抑制这 3 个异常。 一种解决方案可能是创建一个装饰器,如:
from functools import wraps
class ReadonlyFieldError(Exception):
pass
def catch_field_exception(func):
"""
Django silenty suppresses AttributeError, ValueError, ObjectDoesNotExist exceptions that occur during processing of
custom readonly admin fields.
Add this decorator to re-raise exception so it is not missed
:param func:
:return:
"""
@wraps(func)
def wrapped_func(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
raise ReadonlyFieldError('Exception occurred while processing Admin field "{}": {}'.format(func.__name__,
str(e))) from e
return wrapped_func
然后用这个装饰你的方法:
class MyModel(Model):
created = models.DateTimeField(default=datetime.utcnow)
@catch_field_exception
@property
def my_property(self):
raise ValueError('Is anyone there')