Django:ProtectedError 异常处理不起作用



我正在尝试处理 ProtectedError 异常并尝试在我的模板中发布自定义错误消息。

def delete(self, request, *args, **kwargs):
    obj = self.get_object()
    get_success_url = self.get_success_url()
    try:
        obj.delete()
        messages.success(self.request, self.success_message % obj.__dict__)
    except ProtectedError:
        messages.success(self.request, "can't delete")
    return super().delete(request, *args, **kwargs)
如果没有保护错误,

它会将我发送回我的列表页面,并显示删除成功消息,但对于受保护错误,它将我发送到一些通用错误页面,并在/settings/currency/1/delete/消息中使用 ProtectedError。

谢谢。

在我看来,在这两种情况下,您的回报都是相同的:

return super().delete(request, *args, **kwargs)

相反,您除外,请引发错误:

raise ProtectedError('Cannot remove meta user instances', None)

或类似的东西:

    try:
        obj.delete()
        return JsonResponse({})
    except ProtectedError as e:
        return self.status_msg(e[0], status=405) 

看看这些例子

另一个可选,你也可以通过创建新的装饰器来处理它:

from functools import wraps
from django.utils.translation import gettext_lazy as _
from django.db.models.deletion import ProtectedError
from rest_framework.exceptions import PermissionDenied

def protected_error_as_api_error():
    """
    Decorator to handle all `ProtectedError` error as API Error,
    which mean, converting from error 500 to error 403.
    """
    def decorator(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            try:
                return func(request, *args, **kwargs)
            except ProtectedError as error:
                raise PermissionDenied(_('Action Denied: The selected object is being used '
                                         'by the system. Deletion not allowed.'))
        return wrapper
    return decorator

使用示例:

from django.utils.decorators import method_decorator
from yourapp.decorators.protected_error_as_api_error import protected_error_as_api_error
@method_decorator(protected_error_as_api_error())
def delete(self, request, *args, **kwargs):
    ....

# OR

@method_decorator(protected_error_as_api_error())
def destroy(self, request, *args, **kwargs):
    ....

# OR
@action(methods=['delete'], ...):
@method_decorator(protected_error_as_api_error())
def your_view_name(self, request, *args, **kwargs):
    ....

CBV DeleteView使用表单(http://ccbv.co.uk/projects/Django/4.0/django.views.generic.edit/DeleteView/(,这是运行验证和处理错误的推荐方式。

def post(self, request, *args, **kwargs):
    # Set self.object before the usual form processing flow.
    # Inlined because having DeletionMixin as the first base, for
    # get_success_url(), makes leveraging super() with ProcessFormView
    # overly complex.
    self.object = self.get_object()
    form = self.get_form()
    if form.is_valid():
        return self.form_valid(form)
    else:
        return self.form_invalid(form)

只需使用自定义清理方法定义一个自定义表单类,并且仅定义具有 id 的字段即可检索对象:

https://docs.djangoproject.com/en/4.0/ref/forms/api/#django.forms.Form.clean

最新更新