【问题标题】:Django admin not handling ProtectedError exceptionDjango 管理员未处理 ProtectedError 异常
【发布时间】:2018-08-25 20:20:46
【问题描述】:

我有一个 Django 应用程序,它的模型如下:

class Foo(models.Model):
    name = models.CharField(max_length=100)

我在这个模型中有一个特定的实例,它的名字是'bar'(例如),我想防止这个实例被删除。

我已经创建了一个这样的信号接收器:

def protect_foo_bar(sender, instance, using, **kwargs):
    if instance.title != 'bar':
        pass
    else:
        raise ProtectedError(protected_objects=instance, msg='You cannot delete this object')

我已将此接收器连接到pre_delete 信号,如下所示:

pre_delete.connect(receiver=protect_foo_bar, dispatch_uid='protect_foo_bar_signal',
                           sender='app_name.foo')

当我尝试从 Django 的管理面板中删除此特定对象时,它返回异常(错误 500)。是否可以强制管理面板显示类似you cannot delete this object 的错误而不向用户返回异常?

编辑:

这是回溯:

Traceback:

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\core\handlers\exception.py" in inner
  41.             response = get_response(request)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\contrib\admin\options.py" in wrapper
  551.                 return self.admin_site.admin_view(view)(*args, **kwargs)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\contrib\admin\sites.py" in inner
  224.             return view(request, *args, **kwargs)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\utils\decorators.py" in _wrapper
  67.             return bound_func(*args, **kwargs)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\utils\decorators.py" in bound_func
  63.                 return func.__get__(self, type(self))(*args2, **kwargs2)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\contrib\admin\options.py" in changelist_view
  1584.                 response = self.response_action(request, queryset=cl.get_queryset(request))

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\contrib\admin\options.py" in response_action
  1286.             response = func(self, request, queryset)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\contrib\admin\actions.py" in delete_selected
  49.             queryset.delete()

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\db\models\query.py" in delete
  614.         deleted, _rows_count = collector.delete()

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\db\models\deletion.py" in delete
  279.                         sender=model, instance=obj, using=self.using

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\dispatch\dispatcher.py" in send
  193.             for receiver in self._live_receivers(sender)

File "C:\Users\asus\PycharmProjects\AleTaha\env\lib\site-packages\django\dispatch\dispatcher.py" in <listcomp>
  193.             for receiver in self._live_receivers(sender)

File "C:/Users/asus/PycharmProjects/AleTaha\content\signals.py" in protect_content_category
  8.         raise ProtectedError(protected_objects=instance, msg='دسته‌ی «همه» را نمی‌توان حذف کرد.')

Exception Type: ProtectedError at /admin/content/contentcategory/
Exception Value: ('دسته\u200cی «همه» را نمی\u200cتوان حذف کرد.', <ContentCategory: همه>)

【问题讨论】:

  • 可以分享一下traceback吗?
  • @AdamJaamour 是的,我已经添加了回溯。

标签: python django django-admin django-signals


【解决方案1】:

是的,您可以覆盖 ModelAdmindelete_view()response_action() 方法。我还建议覆盖has_delete_permission() 方法,以便根本不会出现“删除”按钮:

class MyModelAdmin(admin.ModelAdmin):

    def delete_view(self, request, object_id, extra_context=None):
        try:
            return super().delete_view(request, object_id, extra_context)
        except ProtectedError:
            msg = "you cannot delete this object"
            self.message_user(request, msg, messages.ERROR)
            opts = self.model._meta
            return_url = reverse(
                'admin:%s_%s_change' % (opts.app_label, opts.model_name),
                args=(object_id,),
                current_app=self.admin_site.name,
            )
            return HttpResponseRedirect(return_url)

    def response_action(self, request, queryset):
        try:
            return super().response_action(request, queryset)
        except ProtectedError:
            msg = "you cannot delete this object"
            self.message_user(request, msg, messages.ERROR)
            opts = self.model._meta
            return_url = reverse(
                'admin:%s_%s_changelist' % (opts.app_label, opts.model_name),
                current_app=self.admin_site.name,
            )
            return HttpResponseRedirect(return_url)

    def has_delete_permission(self, request, obj=None)
        return super().has_delete_permission(request, obj) and (
            not obj or obj.name != 'bar'
        )

【讨论】:

  • 谢谢,当我尝试单击对象页面上的删除按钮时,它可以工作。但不是当我尝试一起删除多个对象时。在删除多个对象时我能做些什么来处理这个异常?
  • 当我看到您的回溯时,我更新了覆盖response_action 的答案。这应该有效,不是吗?
  • 哦,它有效。非常感谢您。在self.model._meta 上有一条警告说access to a protected member of a class。这样可以吗?
  • 是的,访问Model 类的_meta 属性很常见,尽管这是一个“受保护的成员”。对于模型自省非常有用。
猜你喜欢
  • 2012-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-19
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
相关资源
最近更新 更多