Django404 custom handler shows 404 but gives a header of 200

I made my own 404 handler for the authenticated Django website to avoid information leakage.

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') 

Functionally, it does exactly what I want. However, the 404 return page has a status of 200, which is correct for the code. But this, obviously, should be 404 return status.

The raise404 function does not work, because if infinite recursion does not end, it returns here and thus leads to the same problem.

I tried HttpResponseNotFound, but this only takes a string as an argument, and not a template that is not related to DRY-ish.

And I manually tried to set the title using

  response = render_to_response('404.html') response['Status'] = "Not Found - 404" return response 

Then the status header is really set, but the browser still shows 200.

I have no options. Anyone who has clues, please be my hero ... :)

Thanx and welcomes

Gerard.

Change I tried the status field value in all btw types, but no luck :(

+7
Nov 28 '09 at 12:56
source share
6 answers

I would use render_to_string and HttpResponseNotFound , e.g. return HttpResponseNotFound(render_to_string('404.html')) .

+20
Nov 28 '09 at 13:08
source share

I finally discovered why the returned status code did not work. Instead of setting a header message, this is simple:

 response.status_code = 404 

However, the code proposed by PiotrLegnica definitely benefits from simplicity, readability, and beauty. The icon is still standing;)

Hello,

Gerard.

+12
Nov 28 '09 at 15:37
source share

Based on the above suggestions, here is my short version of 404, 500 handlers:

 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 
+7
Aug 02 '13 at 5:54 on
source share

Why don't you just use the Http404 exception?

 if request.user.is_authenticated(): raise Http404 else: return HttpResponseRedirect('/login') 

That should be good for you.

+2
Nov 28 '09 at 16:08
source share

You can do something like the example below.

In your urls.py application add:

 # 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 

In your views.py application add:

 # 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) 

The secret is in the last line: status = 404

Hope this helps!

I look forward to the community contributing to this approach. =)

+1
Apr 26 '13 at 14:11
source share

You can use the render method:

 from django.shortcuts import render 

Returns an HttpResponse whose contents are filled with the result of a call to django.template.loader.render_to_string () with the arguments passed.

By default, RequestContext is used.

Example:

 return render(request, '404.html', status=404) 

And with the keywords:

 return render(request, '404.html', {'data': 'some data'}, status=404) 
+1
Feb 02 '15 at 21:38
source share



All Articles