我正在使用Django进行项目,并且已经投入使用。
在生产环境中,只要发生服务器错误,就会呈现500.html。
如何在开发环境中测试500.html的渲染?或者我如何在开发中渲染500.html,如果我关闭调试我仍然会得到错误而不是500.html
背景:我包含一些基于页面的页面元素,有些在调用500.html时丢失,并且想要在开发环境中调试它。
答案 0 :(得分:47)
我不想关闭DEBUG。相反,我将以下代码段放在urls.py中:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^500/$', 'your_custom_view_if_you_wrote_one'),
(r'^404/$', 'django.views.generic.simple.direct_to_template', {'template': '404.html'}),
)
在上面的代码片段中,错误页面使用自定义视图,您可以轻松地将其替换为Django的direct_to_template视图。
现在,您可以通过调用其网址来测试500和404页:http://example.com/500和http://example.com/404
答案 1 :(得分:27)
在Django 1.6中django.views.generic.simple.direct_to_template
不再存在,这些是我对特殊视图的设置:
# urls.py
from django.views.generic import TemplateView
from django.views.defaults import page_not_found, server_error
urlpatterns += [
url(r'^400/$', TemplateView.as_view(template_name='400.html')),
url(r'^403/$', TemplateView.as_view(template_name='403.html')),
url(r'^404/$', page_not_found),
url(r'^500/$', server_error),
]
答案 2 :(得分:17)
如果您想使用默认的Django 500视图而不是自定义视图:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^500/$', 'django.views.defaults.server_error'),
(r'^404/$', 'django.views.generic.simple.direct_to_template', {'template': '404.html'}),
)
答案 3 :(得分:7)
继续shanyu's answer,在Django 1.3+中使用:
if settings.DEBUG:
urlpatterns += patterns('',
(r'^500/$', 'django.views.defaults.server_error'),
(r'^404/$', 'django.views.defaults.page_not_found'),
)
答案 4 :(得分:5)
两个调试设置都是假的吗?
settings.DEBUG = False
settings.TEMPLATE_DEBUG = False
答案 5 :(得分:1)
urls.py
Transparent
views.py
handler500 = 'project.apps.core.views.handler500'
handler404 = 'project.apps.core.views.handler404'
tests.py
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponseServerError, HttpResponseNotFound
def handler500(request, template_name='500.html'):
t = get_template(template_name)
ctx = Context({})
return HttpResponseServerError(t.render(ctx))
def handler404(request, template_name='404.html'):
t = get_template(template_name)
ctx = Context({})
return HttpResponseNotFound(t.render(ctx))
答案 6 :(得分:1)
我如何操作并测试自定义错误处理程序
根据View
TemplateView
# views.py
from django.views.generic import TemplateView
class ErrorHandler(TemplateView):
""" Render error template """
error_code = 404
template_name = 'index/error.html'
def dispatch(self, request, *args, **kwargs):
""" For error on any methods return just GET """
return self.get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['error_code'] = self.error_code
return context
def render_to_response(self, context, **response_kwargs):
""" Return correct status code """
response_kwargs = response_kwargs or {}
response_kwargs.update(status=self.error_code)
return super().render_to_response(context, **response_kwargs)
告诉django使用自定义错误处理程序
# urls.py
from index.views import ErrorHandler
# error handing handlers - fly binding
for code in (400, 403, 404, 500):
vars()['handler{}'.format(code)] = ErrorHandler.as_view(error_code=code)
自定义错误处理程序的测试用例
# tests.py
from unittest import mock
from django.test import TestCase
from django.core.exceptions import SuspiciousOperation, PermissionDenied
from django.http import Http404
from index import views
class ErrorHandlersTestCase(TestCase):
""" Check is correct error handlers work """
def raise_(exception):
def wrapped(*args, **kwargs):
raise exception('Test exception')
return wrapped
def test_index_page(self):
""" Should check is 200 on index page """
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'index/index.html')
@mock.patch('index.views.IndexView.get', raise_(Http404))
def test_404_page(self):
""" Should check is 404 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 404)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('404 Page not found', response.content.decode('utf-8'))
@mock.patch('index.views.IndexView.get', views.ErrorHandler.as_view(error_code=500))
def test_500_page(self):
""" Should check is 500 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 500)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('500 Server Error', response.content.decode('utf-8'))
@mock.patch('index.views.IndexView.get', raise_(SuspiciousOperation))
def test_400_page(self):
""" Should check is 400 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 400)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('400 Bad request', response.content.decode('utf-8'))
@mock.patch('index.views.IndexView.get', raise_(PermissionDenied))
def test_403_page(self):
""" Should check is 403 page correct """
response = self.client.get('/')
self.assertEqual(response.status_code, 403)
self.assertTemplateUsed(response, 'index/error.html')
self.assertIn('403 Permission Denied', response.content.decode('utf-8'))
答案 7 :(得分:0)
您可以在主handler404
文件中为错误定义handler500
和views.py
,详见答案:
https://stackoverflow.com/a/18009660/1913888
这将返回Django路由到该处理程序时所需的错误。路由到不同的URL名称不需要自定义URL配置。
答案 8 :(得分:0)
在Django版本<3.0中,您应该执行以下操作:
client.py
from unittest import mock
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from django.test import TestCase, override_settings
from .client import Client # Important, we use our own Client here!
class TestErrors(TestCase):
"""Test errors."""
@classmethod
def setUpClass(cls):
super(TestErrors, cls).setUpClass()
cls.username = 'admin'
cls.email = 'admin@localhost'
cls.password = 'test1234test1234'
cls.not_found_url = '/i-do-not-exist/'
cls.internal_server_error_url = reverse('password_reset')
def setUp(self):
super(TestErrors, self).setUp()
User = get_user_model()
User.objects.create_user(
self.username,
self.email,
self.password,
is_staff=True,
is_active=True
)
self.client = Client(raise_request_exception=False)
# Mock in order to trigger Exception and resulting Internal server error
@mock.patch('django.contrib.auth.views.PasswordResetView.form_class', None)
@override_settings(DEBUG=False)
def test_errors(self):
self.client.login(username=self.username, password=self.password)
with self.subTest("Not found (404)"):
response = self.client.get(self.not_found_url, follow=True)
self.assertNotIn('^admin/', str(response.content))
with self.subTest("Internal server error (500)"):
response = self.client.get(self.internal_server_error_url,
follow=True)
self.assertNotIn('TypeError', str(response.content))
tests.py
Client
从Django 3.0开始,您可以跳过自定义tests.py
的定义,而仅使用@PreAuthorize("hasRole('USER')")
中的代码。
答案 9 :(得分:0)
针对Django> 1.6的更新,但未获取
page_not_found() missing 1 required positional argument: 'exception'
受this answer的启发:
# urls.py
from django.views.defaults import page_not_found, server_error, permission_denied, bad_request
[...]
if settings.DEBUG:
# This allows the error pages to be debugged during development, just visit
# these url in browser to see how these error pages look like.
urlpatterns += [
path('400/', bad_request, kwargs={'exception': Exception('Bad Request!')}),
path('403/', permission_denied, kwargs={'exception': Exception('Permission Denied')}),
path('404/', page_not_found, kwargs={'exception': Exception('Page not Found')}),
path('500/', server_error),
答案 10 :(得分:0)
对于 Django > 3.0,只需将 raise_request_exception
值设置为 False
。
from django.test import TestCase
class ViewTestClass(TestCase):
def test_error_page(self):
self.client.raise_request_exception = False
response = self.client.get(reverse('error-page'))
self.assertEqual(response.status_code, 500)
文档:https://docs.djangoproject.com/en/3.2/topics/testing/tools/