2009-11-28 21 views
7

Hice un controlador personalizado404 para un sitio web autenticado de Django para evitar la fuga de información.Django custom handler404 muestra 404 pero da encabezado 200

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

Funcionalmente hace exactamente lo que yo quiero. Sin embargo, la página de retorno 404 tiene un estado 200, que es el código correcto. Pero esto obviamente tiene que ser un estado de devolución 404.

Un raise404 no funciona porque, si no termina en una recursión infinita, vuelve aquí y, por lo tanto, da como resultado el mismo problema.

Probé HttpResponseNotFound, pero esto solo toma una cadena como argumento y no una plantilla, que no es DRY-ish.

Y he intentado manualmente para establecer la cabecera con:

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

A continuación, el encabezado de estado se establece de hecho pero el navegador sigue mostrando un 200.

estoy fuera de opciones .. Cualquier persona que tiene consejos, por favor ser mi héroe ... :)

Gracias y saludos,

Gerard.

Editar: He probado el valor de campo de estado en todo tipo por cierto, pero no hubo suerte :(

+0

no se puede creer lo difícil que me mordió – dirk

Respuesta

20

que haría uso de render_to_string y HttpResponseNotFound, por ejemplo return HttpResponseNotFound(render_to_string('404.html'))

+0

Hmm no me daba cuenta de "render_to_string". Todavía tiene curiosidad sobre por qué no se respetan los códigos de estado del conjunto. De todos modos ... definitivamente te has ganado la insignia de "héroe de alguien" ...;) .. muchas gracias! – GerardJP

12

Finalmente encontré por qué el estado devuelto. . código de trabajo aún no ha lugar de establecer un mensaje de cabecera, sino que simplemente es:

response.status_code = 404 

Sin embargo, el código sugerido por PiotrLegnica definitivamente gana en simplicidad, readabi lidad y la belleza .. La placa sigue en pie;)

Saludos,

Gerard.

2

¿Por qué no solo utiliza la excepción Http404?

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

Eso debería estar bien para usted.

+0

De alguna manera, termino con una respuesta de 500 al subir el Http404. Sin embargo, creo que es necesario que haya una distinción dentro de la función; de lo contrario, terminaré con un error de recursión, o tengo que escribir una vista page_not_found(). Gracias de todos modos. – GerardJP

+0

¿Ha importado Http404 de django.http? – gruszczy

+0

Emphh, cuando lo levantas te redirigen a tu controlador 404. Algunas personas quieren que sean personalizadas. – DataGreed

1

Podría hacer algo como el siguiente ejemplo.

En urls.py complemento de la aplicación:

# 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 

En views.py complemento de la aplicación:

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

El secreto está en la última línea: estado = 404

Esperanza ¡Eso ayudo!

Espero con interés las aportaciones de la comunidad a este enfoque.=)

7

Sobre la base de las sugerencias anteriores, aquí está mi versión corta de 404, 500 manipuladores:

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 
+0

Esta respuesta fue la más fácil de implementar y no necesita ninguna configuración de cusotm urls.py. –

1

Puede utilizar render método:

from django.shortcuts import render 

Devuelve una HttpResponse cuyo contenido es lleno con el resultado de llamando a django.template.loader.render_to_string() con los argumentos pasados.

Utiliza un RequestContext por defecto.

Ejemplo:

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

Y con palabras clave:

return render(request, '404.html', {'data': 'some data'}, status=404) 
Cuestiones relacionadas