Пользовательский обработчик Django404 показывает 404, но выдает заголовок 200
-
06-07-2019 - |
Вопрос
Я создал пользовательский обработчик 404 для аутентифицированного веб-сайта Django, чтобы избежать утечки информации.
def check_logged_in_404(request):
""" Custom 404. Show friendly 404 when logged in and redirect to /login
when not logged in.
"""
if request.user.is_authenticated():
return render_to_response('404.html')
else:
return HttpResponseRedirect('/login')
Функционально он делает именно то, что я хочу.Однако страница возврата 404 имеет статус 200, который является правильным с точки зрения кода.Но это, очевидно, должен быть статус возврата 404.
raise404 не работает, потому что, если он не заканчивается бесконечной рекурсией, он возвращается сюда и, таким образом, приводит к той же проблеме.
Я попробовал HttpResponseNotFound , но это принимает только строку в качестве аргумента, а не шаблон, который не является СУХИМ.
И я вручную попытался установить заголовок с помощью:
response = render_to_response('404.html')
response['Status'] = "Not Found - 404"
return response
Тогда заголовок статуса действительно установлен, но браузер по-прежнему отображает значение 200.
У меня нет выбора ..Любой, у кого есть чаевые, пожалуйста, будьте моим героем ...:)
Спасибо и с уважением,
Джерард.
Редактировать:Кстати, я попробовал значение поля status во всех сортировках, но безуспешно: (
Решение
Я бы использовал render_to_string
и HttpResponseNotFound
, например return HttpResponseNotFound(render_to_string('404.html'))
.
Другие советы
Наконец-то я нашел, почему возвращенный код состояния не сработал.Вместо установки сообщения в заголовке, это просто:
response.status_code = 404
Тем не менее, код, предложенный PiotrLegnica, определенно выигрывает в простоте, удобочитаемости и красоте..Значок все еще стоит ;)
С уважением,
Джерард.
Основываясь на приведенных выше предложениях, вот моя краткая версия 404, 500 обработчиков:
def handler404(request):
response = render_to_response('404.html', {},
context_instance=RequestContext(request))
response.status_code = 404
return response
def handler500(request):
response = render_to_response('500.html', {},
context_instance=RequestContext(request))
response.status_code = 500
return response
Почему бы вам просто не использовать исключение Http404?
if request.user.is_authenticated():
raise Http404
else:
return HttpResponseRedirect('/login')
Для тебя это должно быть просто прекрасно.
Вы могли бы сделать что-то вроде приведенного ниже примера.
В вашем приложении urls.py добавьте:
# Imports
from django.conf.urls.static import static
from django.conf.urls import handler404
from django.conf.urls import patterns, include, url
from yourapplication import views
##
# Handles the URLS calls
urlpatterns = patterns('',
# url(r'^$', include('app.homepage.urls')),
)
handler404 = views.error404
В вашем приложении views.py добавьте:
# Imports
from django.shortcuts import render
from django.http import HttpResponse
from django.template import Context, loader
##
# Handle 404 Errors
# @param request WSGIRequest list with all HTTP Request
def error404(request):
# 1. Load models for this view
#from idgsupply.models import My404Method
# 2. Generate Content for this view
template = loader.get_template('404.htm')
context = Context({
'message': 'All: %s' % request,
})
# 3. Return Template for this view + Data
return HttpResponse(content=template.render(context), content_type='text/html; charset=utf-8', status=404)
Секрет кроется в последней строке:статус=404
Надеюсь, это помогло!
Я с нетерпением жду вклада сообщества в этот подход.=)
Вы можете использовать render
способ:
from django.shortcuts import render
Возвращает HttpResponse, содержимое которого заполнено результатом вызова django.template.loader.render_to_string() с переданными аргументами.
По умолчанию использует RequestContext.
Пример:
return render(request, '404.html', status=404)
И с ключевыми словами:
return render(request, '404.html', {'data': 'some data'}, status=404)