【发布时间】:2021-03-30 02:06:42
【问题描述】:
我知道settings.DEBUG 在生产中应该是False。
不过,如果当前用户被认证为管理员,我想在生产中展示出色的 django 调试视图。
我阅读了Error Reporting Docs,但找不到将其打开的设置。
如果启用不同的调试视图更容易,那就太好了。至少我希望看到一个不错的堆栈跟踪,以便快速了解错误的来源(无需查看日志)。
【问题讨论】:
标签: django
我知道settings.DEBUG 在生产中应该是False。
不过,如果当前用户被认证为管理员,我想在生产中展示出色的 django 调试视图。
我阅读了Error Reporting Docs,但找不到将其打开的设置。
如果启用不同的调试视图更容易,那就太好了。至少我希望看到一个不错的堆栈跟踪,以便快速了解错误的来源(无需查看日志)。
【问题讨论】:
标签: django
我宁愿选择像Sentry 这样的工具来跟踪生产环境中的错误。
Sentry 是一个应用监控平台,可以帮助每个开发者 诊断、修复和优化代码的性能。
Sentry 也支持Django monitoring-(doc)。此配置会将错误发送到 Sentry 仪表板,我们也将能够看到堆栈跟踪。
此外,这将跟踪整个应用程序,不仅针对视图,不仅针对超级用户等
恕我直言,更改 settings.DEBUG 是个坏主意,您迟早会因此面临许多问题。
【讨论】:
您可以在根 URLConf 中添加自定义错误处理视图,请参阅Django docs 了解更多信息。 500 错误的默认视图是 django.views.defaults.server_error,如果用户不是管理员,您可以返回它,否则返回 django.views.debug.technical_500_response。但是,请注意 django.views.debug.technical_500_response 并未在 Django 文档中公开记录,因此在未来的版本中可能会(或可能不会)更改。
所以,最后你的代码可能是这样的:
your_project_name/urls.py
urlpatterns = [
...
]
from django.views.debug import technical_500_response
from django.views.defaults import server_error
def handler500(request):
if request.user.is_superuser:
return technical_500_response(request, *sys.exc_info())
else:
return server_error(request)
请注意,DEBUG=True 时根本不会调用此处理程序
【讨论】:
我也觉得有必要偶尔详细检查一下生产环境,并使用一些简单的策略:
(1) 您可能知道,您可以在项目设置中添加一个 ADMINS 列表,以通过电子邮件接收通常在开发中显示的“黄色调试屏幕”的副本;见:
https://docs.djangoproject.com/en/3.1/ref/settings/#admins
(2)为了在生产中做更多的检查,我一般会安装django-debug-toolbar,配置如下:
def show_toolbar(request):
from constance import config
try:
if not config.DEBUG_SHOW_TOOLBAR:
return False
except:
return False
return request.user.is_superuser
DEBUG_TOOLBAR_PATCH_SETTINGS = False
INTERNAL_IPS = ('127.0.0.1', )
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': 'main.settings.settings.show_toolbar',
}
DEBUG_TOOLBAR_PANELS = [
'debug_toolbar.panels.versions.VersionsPanel',
...
工具栏通常是隐藏的,除非我启用 DEBUG_SHOW_TOOLBAR 标志(我使用 django-constance 进行动态设置);将 DEBUG_SHOW_TOOLBAR 设置为 True,调试面板将显示给主管。
(3) 最后,我总是在我的项目中包含这个 sn-p:
文件'main/settings/debug.py'
from main.settings.local import *
DEBUG = True
ALLOWED_HOSTS = ['*', ]
(作为“main/setting/local.py”我的默认设置)
作为最后的手段,我可以快速临时通过 SSH 运行项目的调试实例,如下所示:
python manage.py runserver --settings=main.settings.debug 0.0.0.0:8000
然后在端口 8000 上以 DEBUG 模式访问该站点
【讨论】:
您可以使用 Django 的 @override_settings 装饰器动态更改 settings.DEBUG 值,例如:
from django.test.utils import override_settings
from django.conf import settings
class TestSomething(TestCase):
@override_settings(DEBUG=True)
def test_debug(self):
assert settings.DEBUG
由于您希望仅为管理员启用调试,您只需实现一个方法来计算是否应为当前用户启用调试,例如 @override_settings(DEBUG=cur_user_is_admin())
另一种方法是使用自定义 500 处理程序和内置 django 500 错误处理程序自己制作调试消息。 Please see this answer 了解更多信息。
【讨论】:
首先,我 100% 同意 @JPG 的回答,即这几乎可以肯定是一个坏主意(出于一些实用/调试/安全原因):
debug == True”的思维方式。这只会很糟糕。我也会推荐 sentry(或类似于 sentry 的工具):
说了这么多,我还是要说怎么做,只是因为它很有趣。您首先需要了解 django 在处理错误时所做的工作。
get_reponse,在出现异常时调用response_for_exception。process_exception 视图都将以相反的顺序调用(直到返回响应 - 不会再调用 process_exceptions)response_for_exception 装饰)。response_for_exception 是动作发生的地方。 Django:
在继续之前,请先查看response_for_exception。当调试打开/关闭时,您将看到哪些错误的处理方式不同。
您将看到一些错误具有在调试打开时调用的特定视图。您可以实现自定义 400、404 和 500 视图来模拟该行为。
from django.views import debug, defaults
def handler400(request):
if request.user.is_superuser:
# Be sure to apply the correct code:
return debug.technical_500_response(request, *sys.exc_info(), status_code=400)
else:
# You should probably have your own 400 page here
# but otherwise:
return defaults.bad_request(request)
def handler404(request):
if request.user.is_superuser:
return debug.technical_404_response(request, exc)
else:
# Likewise, you should probably have a pretty 404 page here
# but otherwise:
return defaults.page_not_found(request)
def handler500(request):
if request.user.is_superuser:
return debug.technical_500_response(request, *sys.exc_info())
else:
# Likewise, you should probably have a pretty 500 page here
# but otherwise:
return defaults.server_error(request)
【讨论】: