如何防止Django的管理界面静默抑制错误?

时间:2018-12-01 18:32:54

标签: django django-admin

假设我有一个简单的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显示异常?

1 个答案:

答案 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')