Categorías
Python

Enchufe de Programación en Python (Guía)

 

Tabla de Contenidos

  • Django redirecciones: Un simple estupendo Ejemplo
  • Por qué redirección
  • Detrás de las escenas: ¿Cómo una imprimación WorksA rápida redirección HTTP en HTTPHTTP redirecciones Estado CodesTemporary vs. redirecciones permanentes
  • Una cartilla rápida en HTTP
  • HTTP redirecciones Códigos de estado
  • temporal frente a la permanente redirecciones
  • redirecciones en DjangoThe HttpResponseRedirect ClassThe redirección () FunctionThe RedirectView Class-Based Ver
  • La Clase HttpResponseRedirect
  • La redirección () Función
  • El RedirectView Class-Based Ver
  • avanzada UsagePassing Los parámetros con códigos de redirección RedirectsSpecial
  • pasar parámetros con los códigos de redirecciones
  • de redireccionamiento especial
  • PitfallsRedirects que se acaba de no RedirectRedirects Eso sólo no se detendrá RedirectingPermanent redirecciones Redirecciones PermanentUnvalidated pueden comprometer la seguridad
  • redirecciones que el jus t Will no redirige
  • redireccionamientos que se acaba de parada no redireccionante
  • redirecciones permanentes son permanentes
  • no validados redireccionamientos pueden comprometer la seguridad
  • Resumen
  • Referencias
  • Una cartilla rápida sobre HTTP
  • redirecciones HTTP Códigos de estado
  • temporal vs. redirecciones permanentes
  • El HttpResponseRedirect Clase
  • La redirección () Función
  • El RedirectView Class-Based Ver
  • pasar parámetros con los códigos de redirecciones
  • de redireccionamiento especial
  • redirecciones que acaba de ganar’ t redireccionamiento
  • redireccionamientos que se acaba de parada no redireccionante
  • redirecciones permanentes son permanentes
  • no validados redireccionamientos pueden comprometer la seguridad

Cuando se construye una aplicación web de Python con el marco de Django, usted en algún momento tiene que redirección el usuario de un URL para anothe r.

En esta guía, aprenderá todo lo que necesita saber acerca de las redirecciones HTTP y cómo tratar con ellos en Django. Al final de este tutorial, podrás:

  • ser capaz de redirigir a un usuario de una URL a otra URL
  • saber la diferencia entre redirecciones temporales y permanentes
  • trampas Evitar comunes cuando se trabaja con redirecciones

Este tutorial asume que está familiarizado con los bloques de construcción básicos de una aplicación Django, como puntos de vista y patrones de URL.

Django redirecciones: Un simple estupendo Ejemplo

En Django, redirigir al usuario a otra URL devolviendo una instancia de HttpResponseRedirect o HttpResponsePermanentRedirect desde su punto de vista. La forma más sencilla de hacerlo es utilizar la redirección () la función de los django.shortcuts módulo. He aquí un ejemplo:

# views.py
from django.shortcuts import redirect

def redirect_view(request):
response = redirect('/redirect-success/')
return response

Sólo redirección de llamadas () con una dirección URL en la vista. Se volverá una clase HttpResponseRedirect, que luego regrese de su vista.

una vista que devuelve un redireccionamiento tiene que ser añadido a su urls.py, al igual que cualquier otro punto de vista:

# urls.py
from django.urls import path

from .views import redirect_view

urlpatterns = [
path('/redirect/', redirect_view)
# ... more URL patterns here
]

Asumiendo que este es el principal urls.py de su proyecto de Django, la URL / redirección / ahora redirige a / redirección éxito /.

Para evitar la codificación dura de la URL, puede llamar redirección () con el nombre de una vista o patrón de URL o un modelo para evitar la codificación dura de la URL de redirección. También puede crear una redirección permanente pasando el argumento de palabra clave = True permanente.

Este artículo podría terminar aquí, pero entonces no podría ser llamada “La última guía a Django vuelve a dirigir.” Vamos a echar un vistazo más de cerca a la función de redirección () en un minuto y también entrar en los detalles esenciales de los códigos de estado HTTP y diferentes clases HttpRedirectResponse, pero vamos a echar un paso atrás y empezar con una pregunta fundamental.

Por qué redirección

Usted podría preguntarse por qué usted quiere nunca para redirigir un usuario a una URL diferente en el primer lugar. Para tener una idea de dónde redirecciones tienen sentido, echar un vistazo a cómo Django incorpora redirecciones en las características que el marco proporciona de forma predeterminada:

  • Cuando no está en el sistema de entrada y solicita una dirección URL que requiere autenticación, como la administración de Django, Django le redirige a la página de inicio de sesión.
  • Al iniciar la sesión con éxito, Django le redirige a la URL solicitada originalmente.
  • Cuando cambie su contraseña a través del sitio administrativo, se le redirige a una página que indica que el cambio se ha realizado correctamente.
  • Cuando se crea un objeto en la administración de Django, Django le redirige a la lista de objetos.

¿Cómo sería una implementación alternativa sin redirecciones parece? Si un usuario tiene que iniciar sesión para ver una página, simplemente podría mostrar una página que dice algo así como “Haga clic aquí para iniciar sesión.” Esto funciona, pero sería inconveniente para el usuario. acortadores de URL como

http://bit.ly son otro ejemplo de que las redirecciones son útiles: escribir una breve URL en la barra de direcciones del navegador y luego redirige a una página con una URL larga, difícil de manejar.

En otros casos, las redirecciones no son sólo una cuestión de conveniencia. Redirecciones son instrumento fundamental para guiar al usuario a través de una aplicación web. Después de realizar algún tipo de operación con efectos secundarios, como la creación o eliminación de un objeto, es una buena práctica para redirigir a otra URL para evitar que realiza la operación dos veces por accidente.

Un ejemplo de este uso de redirecciones es de manipulación de formas, donde un usuario es redirigido a otro URL después de la presentación con éxito una forma. He aquí un ejemplo de código que ilustra cómo habitualmente se maneja un formulario:

1 from django import forms
2 from django.http import HttpResponseRedirect
3 from django.shortcuts import redirect, render
4
5 def send_message(name, message):
6 # Code for actually sending the message goes here
7
8 class ContactForm(forms.Form):
9 name = forms.CharField()
10 message = forms.CharField(widget=forms.Textarea)
11
12 def contact_view(request):
13 # The request method 'POST' indicates
14 # that the form was submitted
15 if request.method == 'POST': # 1
16 # Create a form instance with the submitted data
17 form = ContactForm(request.POST) # 2
18 # Validate the form
19 if form.is_valid(): # 3
20 # If the form is valid, perform some kind of
21 # operation, for example sending a message
22 send_message(
23 form.cleaned_data['name'],
24 form.cleaned_data['message']
25 )
26 # After the operation was successful,
27 # redirect to some other page
28 return redirect('/success/') # 4
29 else: # 5
30 # Create an empty form instance
31 form = ContactForm()
32
33 return render(request, 'contact_form.html', {'form': form})

El propósito de este punto de vista es mostrar y manejar un formulario de contacto que permite al usuario enviar un mensaje. Vamos a seguir paso a paso: En primer lugar

La vista se ve en el método de la petición. Cuando el usuario visita la URL conectado a este punto de vista, el navegador realiza una petición GET.

Si la vista es llamada con una solicitud POST, los datos POST se utiliza para crear instancias de un objeto ContactForm.

Si el formulario es válido, los datos del formulario se pasa a send_message (). Esta función no es relevante en este contexto y por lo tanto no se muestra aquí.

Después de enviar el mensaje, la vista devuelve una redirección a la URL / éxito /. Este es el paso que nos interesa. Por simplicidad, la URL está codificada aquí. Verá más adelante cómo se puede evitar eso.

Si la vista recibe una petición GET (o, para ser más precisos, cualquier tipo de petición que no es una petición POST), se crea una instancia de ContactForm y usos django.shortcuts.render () para hacer que la plantilla contact_form.html .

Si el usuario vuelve a cargar ahora, sólo el / éxito / URL se vuelve a cargar. Sin la redirección, volver a cargar la página sería volver a enviar el formulario y enviar otro mensaje.

Detrás de las escenas: ¿Cómo una redirección HTTP Obras

Ahora se sabe por qué redirecciones tienen sentido, pero ¿cómo funcionan? Vamos a echar un rápido resumen de lo que sucede cuando se introduce una URL en la barra de direcciones del navegador web.

Una cartilla rápida sobre HTTP de

Let asume que ha creado una aplicación Django con el fin de “Hello World” que se encarga de la ruta / hola /. Usted está ejecutando la aplicación con el servidor de desarrollo de Django, por lo que la URL completa es http://127.0.0.1:8000/hello/.

Cuando se introduce la URL en su navegador, se conecta al puerto 8000 en el servidor con la dirección IP 127.0.0.1 y envía una solicitud HTTP GET para la ruta / hola /. El servidor responde con una respuesta HTTP.

HTTP está basado en texto, por lo que es relativamente fácil mirar a la ida y vuelta entre el cliente y el servidor. Puede utilizar la herramienta de rizo línea de comandos con la opción –include a echar un vistazo a la respuesta HTTP completa, incluyendo las cabeceras, así:

$ curl --include http://127.0.0.1:8000/hello/
HTTP/1.1 200 OK
Date: Sun, 01 Jul 2018 20:32:55 GMT
Server: WSGIServer/0.2 CPython/3.6.3
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 11

Hello World

Como se puede ver, una respuesta HTTP se inicia con una línea de estado que contiene un estatus código y un mensaje de estado. La línea de estado es seguido por un número arbitrario de cabeceras HTTP. Una línea en blanco indica el final de las cabeceras y el inicio del cuerpo de la respuesta, que contiene los datos reales del servidor quiera guardar.

redirecciones HTTP Códigos de estado

¿Cómo es una respuesta de redirección como? Asumamos la ruta / redirección / es manejado por redirect_view (), se mostró anteriormente. Si accede a http://127.0.0.1:8000/redirect/ con rizo, su apariencia de la consola como esta:

$ curl --include http://127.0.0.1:8000/redirect/
HTTP/1.1 302 Found
Date: Sun, 01 Jul 2018 20:35:34 GMT
Server: WSGIServer/0.2 CPython/3.6.3
Content-Type: text/html; charset=utf-8
Location: /redirect-success/
X-Frame-Options: SAMEORIGIN
Content-Length: 0

Las dos respuestas pueden parecer similares, pero hay algunas diferencias clave. La redirección:

  • un código de estado diferente (302 frente a 200)
  • Contiene una cabecera Location con un pariente URL
  • termina con una línea vacía debido a que el cuerpo de la respuesta de redirección está vacía

El principal diferenciador es la código de estado. La especificación de la norma HTTP dice lo siguiente:

El 302 (encontrado) código de estado indica que reside el recurso objetivo temporalmente bajo una diferente URI. Dado que el cambio de dirección podría ser alterado en algunas ocasiones, el cliente debe seguir utilizando el URI de la solicitud efectiva para futuras solicitudes. El servidor debe generar un campo de cabecera Ubicación en la respuesta que contiene una referencia URI para los diferentes URI. El agente de usuario puede utilizar el valor del campo de localización de la redirección automática. (Fuente)

En otras palabras, cada vez que el servidor envía un código de estado de 302, que dice al cliente, “Hey, por el momento, lo que busca se puede encontrar en este otro lugar.”

Una frase clave en la especificación es “puede usar el valor del campo Ubicación para la redirección automática”. Esto significa que no se puede forzar al cliente a cargar otra URL. El cliente puede optar por esperar la confirmación del usuario o decidir no cargar la URL en absoluto.

Ahora se sabe que una redirección es sólo una respuesta HTTP con un código de estado 3xx y una cabecera Location. La conclusión clave aquí es que una redirección HTTP es como cualquier respuesta HTTP de edad, pero con un cuerpo vacío, código de estado 3xx, y una cabecera Location.

Eso es todo. Ataremos esta de nuevo en Django por un momento, pero primero vamos a echar un vistazo a dos tipos de redirecciones en ese rango de código de estado 3xx y ver por qué son importantes cuando se trata de desarrollo web.

temporal frente a la permanente redirecciones HTTP

Los previsto por la norma varios códigos de estado de redirección, todo en la gama 3xx. Los dos más comunes son los códigos de estado 301 Redirección permanente y 302 encontrados. código de estado

A 302 Encontrado indica una redirección temporal. Una redirección temporal dice, “Por el momento, lo que está buscando se puede encontrar en esta otra dirección.” Piense en ello como una señal de tienda que dice: “Nuestra tienda está cerrada por reformas. Por favor, vaya a nuestra otra tienda de la esquina “. Como esto es sólo temporal, usted comprueba la dirección original la próxima vez que vaya de compras.

Nota: En HTTP 1.0, el mensaje de código de estado 302 fue Redirección temporal. El mensaje fue cambiado a encontrados en HTTP 1.1.

Como su nombre lo indica, redirecciones permanentes se supone que deben ser permanentes. Una redirección permanente indica al navegador, “Lo que estás buscando ya no está en esta dirección. Es ahora en esta nueva dirección, y nunca estará en la antigua dirección de nuevo.”

Una redirección permanente es como un signo tienda que dice: “Nos mudamos. Nuestra nueva tienda está a la vuelta de la esquina “. Este cambio es permanente, por lo que la próxima vez que quiera ir a la tienda, que iría directamente a la nueva dirección.

Nota: redirecciones permanentes pueden tener consecuencias no deseadas. Termina esta guía antes de utilizar una redirección permanente o saltar directamente a la sección de “redirecciones permanentes son permanentes.”

Navegadores comportan de manera similar al manejar las redirecciones: cuando una URL devuelve una respuesta de redirección permanente, esta respuesta se almacena en caché. La próxima vez que el navegador encuentra la dirección de edad, recuerda la redirección y solicita directamente la nueva dirección. El almacenamiento en caché

una redirección ahorra una solicitud innecesario y hace que para una mejor y más rápida experiencia de usuario.

Por otra parte, la distinción entre las redirecciones temporales y permanentes es relevante para la optimización del motor de búsqueda.

redirecciones en Django

Ahora se sabe que una redirección es sólo una respuesta HTTP con un código de estado 3xx y una cabecera Location.

Se puede construir una respuesta así a sí mismo de un objeto HttpResponse normal:

def hand_crafted_redirect_view(request):
response = HttpResponse(status=302)
response['Location'] = '/redirect/success/'
return response

Esta solución es técnicamente correcto, pero se trata de un poco de escribir.

El HttpResponseRedirect Clase

Puede ahorrarse algo de tecleo con la clase HttpResponseRedirect, una subclase de HttpResponse. Sólo una instancia de la clase con la URL que desee redirigir como primer argumento, y la clase fijará el estado correcto y cabecera Location:

def redirect_view(request):
return HttpResponseRedirect('/redirect/success/')

Se puede jugar con la clase HttpResponseRedirect en el terminal de Python para ver lo que está recibiendo :

>>> from django.http import HttpResponseRedirect
>>> redirect = HttpResponseRedirect('/redirect/success/')
>>> redirect.status_code
302
>>> redirect['Location']
'/redirect/success/'

también hay una clase para redirecciones permanentes, que es bien llamado HttpResponsePermanentRedirect. Funciona de la misma como HttpResponseRedirect, la única diferencia es que no tiene un código de estado de 301 (movido permanentemente).

Note: En las ejemplos anteriores, las direcciones URL de redirección están codificadas. URL codificación dura es una mala práctica: si el URL cambia nunca, usted tiene que buscar a través de todo el código y cambiar cualquier ocurrencia. Vamos a arreglar eso!

Usted podría utilizar django.urls.reverse () para construir una URL, pero hay una manera más conveniente como se verá en la siguiente sección.

La redirección () Función

Para hacer la vida más fácil, Django proporciona la función de acceso directo versátil que ya hemos visto en la introducción: django.shortcuts.redirect ().

Usted puede llamar a esta función con: instancia de modelo

  • A, o cualquier otro objeto, con un método get_absolute_url ()
  • una URL o nombre de la vista y / argumentos posicionales y o palabra clave
  • Una URL

Será tomar las medidas apropiadas para hacer volver los argumentos en una URL y devolver un HTTPResponseRedirect.If que pase permanente = True, devolverá una instancia de HttpResponsePermanentRedirect, lo que resulta en una redirección permanente.

Aquí hay tres ejemplos para ilustrar los diferentes casos de uso:

Pasando un modelo: redirección

from django.shortcuts import redirect

def model_redirect_view(request):
product = Product.objects.filter(featured=True).first()
return redirect(product)

() llamará product.get_absolute_url () y utilizar el resultado como objetivo redireccionamiento. Si la clase determinada, en este caso del producto, no tiene un método get_absolute_url (), se producirá un error con un TypeError.

pasar un nombre de URL y argumentos:

from django.shortcuts import redirect

def fixed_featured_product_view(request):
...
product_id = settings.FEATURED_PRODUCT_ID
return redirect('product_detail', product_id=product_id)

redirección () tratará de utilizar sus argumentos dados para revertir una dirección URL. Este ejemplo asume sus patrones de URL contienen un patrón de esta manera:

path('/product//', 'product_detail_view', name='product_detail')

pasar una URL:

from django.shortcuts import redirect

def featured_product_view(request):
return redirect('/products/42/')

redirección () tratará cualquier cadena que contenga una / o. como una dirección URL y utilizarlo como objetivo del redireccionamiento.

El RedirectView Class-Based Ver

Si se tiene una vista que no hace más que devolver una redirección, se podría utilizar la clase de vista basados ​​en django.views.generic.base.RedirectView.

usted puede adaptar a sus necesidades RedirectView a través de diversos atributos.

Si la clase tiene un atributo .url, se utiliza como una URL de redireccionamiento. Cuerda marcadores de posición de formato se sustituyen con argumentos con nombre de la URL: Modelo

# urls.py
from django.urls import path
from .views import SearchRedirectView

urlpatterns = [
path('/search//', SearchRedirectView.as_view())
]

# views.py
from django.views.generic.base import RedirectView

class SearchRedirectView(RedirectView):
url = 'https://google.com/?q=%(term)s'

El URL define un plazo argumento, que se utiliza en SearchRedirectView para construir el URL de redirección. El camino / Búsqueda / gatitos / en su aplicación le redirigirá a https://google.com/?q=kittens.

En lugar de la subclasificación RedirectView para sobrescribir el atributo url, también puede pasar la URL argumento de palabra clave a as_view () en sus urlpatterns:

#urls.py
from django.views.generic.base import RedirectView

urlpatterns = [
path('/search//',
RedirectView.as_view(url='https://google.com/?q=%(term)s')),
]

Usted puede también get_redirect_url sobreescritura () para obtener un comportamiento completamente personalizado:

from random import choice
from django.views.generic.base import RedirectView

class RandomAnimalView(RedirectView):

animal_urls = ['/dog/', '/cat/', '/parrot/']
is_permanent = True

def get_redirect_url(*args, **kwargs):
return choice(self.animal_urls)

Esta clase basados ​​en vista redirige a una URL recogidos al azar de .animal_urls.

django.views.generic.base.RedirectView ofrece unos más ganchos para la personalización. Esta es la lista completa:

  • .urlIf este atributo se establece, debe ser una cadena con una URL para redirigir a. Si contiene el formato de cadenas como marcadores de posición% (name) s, que se expanden utilizando los argumentos de palabras clave se pasan a la vista.
  • .pattern_nameIf este atributo se establece, debe ser el nombre de un patrón de URL para redirigir a. Todos los argumentos posicionales y de palabras clave se pasan a la vista se utilizan para revertir el patrón de URL.
  • .permanentIf este atributo es cierto que la vista devuelve una redirección permanente. Por defecto es falso.
  • .query_stringIf este atributo es cierto que el punto de vista añade cualquier cadena de consulta proporcionada a la URL de redireccionamiento. Si es falsa, que es la predeterminada, la cadena de consulta se descarta. get_redirect_url
  • (args *, ** kwargs) Este método es responsable de construir la URL de redireccionamiento. Si este método devuelve Ninguno, la vista devuelve una implementación por defecto 410 status.The Atrás comprueba primero .url. Se trata .url como una cadena de formato “viejo estilo”, utilizando los parámetros de URL nombrados pasados ​​a la vista para expandir cualquier formato de .url specifiers.If llamada no se establece, comprueba si .pattern_name se establece. Si lo es, se lo utiliza para revertir una dirección URL con argumentos posicionales y de palabras clave que received.You puede cambiar ese comportamiento en la forma que desee al sobrescribir este método. Sólo asegúrese de que devuelve una cadena que contiene una URL.

.url

Si este atributo se establece, debe ser una cadena con una URL para redirigir a. Si contiene el formato de cadenas como marcadores de posición% (name) s, que se expanden utilizando los argumentos de palabras clave se pasan a la vista.

.pattern_name

Si este atributo se establece, debe ser el nombre de un patrón de URL para redirigir a. Todos los argumentos posicionales y de palabras clave se pasan a la vista se utilizan para revertir el patrón de URL.

.permanent

Si este atributo es cierto que la vista devuelve una redirección permanente. Por defecto es falso.

.query_string

Si este atributo es cierto que el punto de vista añade cualquier cadena de consulta proporcionada a la URL de redireccionamiento. Si es falsa, que es la predeterminada, la cadena de consulta se descarta.

get_redirect_url (* args, ** kwargs)

Este método es responsable de construir la URL de redireccionamiento. Si este método devuelve None, la vista devuelve un estado Atrás 410. comprueba primero

la implementación predeterminada .url. Se trata .url como una cadena de formato “viejo estilo”, utilizando los parámetros de URL con nombre que se pasan al objeto de ampliar los especificadores de formato mencionadas.

Si .url no está establecido, comprueba si es .pattern_name conjunto. Si lo es, se lo utiliza para revertir una dirección URL con argumentos posicionales y de palabras clave que ha recibido.

Puede cambiar ese comportamiento en la forma que desee al sobrescribir este método. Sólo asegúrese de que devuelve una cadena que contiene una URL.

Nota: puntos de vista basados ​​en la clase son un concepto poderoso, pero puede ser un poco difícil de envolver su cabeza alrededor. A diferencia de puntos de vista basados ​​en funciones regulares, en las que es relativamente fácil de seguir el flujo del código, puntos de vista basados ​​en clases se componen de una compleja jerarquía de mixins y clases base.

Una gran herramienta para dar sentido a una clase de vista basado en la clase es el sitio web Vistas con clase basada en la clase.

Se podría implementar la funcionalidad de RandomAnimalView en el ejemplo anterior con este simple vista basado en las funciones:

from random import choice
from django.shortcuts import redirect

def random_animal_view(request):
animal_urls = ['/dog/', '/cat/', '/parrot/']
return redirect(choice(animal_urls))

Como se puede ver, el enfoque basado en la clase no proporciona ningún beneficio obvio al tiempo que añade cierta complejidad oculta. Esto plantea la pregunta: ¿cuándo se debe utilizar RedirectView?

Si desea agregar una redirección directamente en su urls.py, utilizando RedirectView tiene sentido. Pero si usted se encuentra el sobreescribiendo get_redirect_url, una visión basada en la función podría ser más fácil de entender y más flexible para futuras mejoras. Uso

avanzada

Una vez que sabe que es probable que desee utilizar django.shortcuts.redirect (), redirigir a una URL diferente es bastante sencilla. Pero hay un par de casos de uso avanzadas que no son tan evidentes.

Paso de parámetros con redirecciones

A veces, se desea pasar algunos parámetros a la vista que se está realizando el redireccionamiento a. Su mejor opción es pasar los datos en la cadena de consulta de URL de redireccionamiento, que significa volver a dirigir a un URL como esta: de

http://example.com/redirect-path/?parameter=value

Let suponga que desea redirigir desde some_view () para product_view (), pero pasar a una categoría de parámetro opcional :

from django.urls import reverse
from urllib.parse import urlencode

def some_view(request):
...
base_url = reverse('product_view') # 1 /products/
query_string = urlencode({'category': category.id}) # 2 category=42
url = '{}?{}'.format(base_url, query_string) # 3 /products/?category=42
return redirect(url) # 4

def product_view(request):
category_id = request.GET.get('category') # 5
# Do something with category_id

el código de este ejemplo es bastante denso, así que vamos a seguir paso a paso:

en primer lugar, se utiliza django.urls.reverse () para obtener la asignación de dirección URL a product_view ().

A continuación, usted tiene que construir la cadena de consulta. Esa es la parte que sigue al signo de interrogación. Es aconsejable el uso de urllib.urlparse.urlencode () para que, a medida que se encargará de codificar correctamente todos los caracteres especiales.

Ahora usted tiene que unirse base_url y query_string con un signo de interrogación. Una cadena de formato funciona bien para eso.

Por último, se pasa url para django.shortcuts.redirect () o para una clase de respuesta de redirección.

En product_view (), el objetivo del redireccionamiento, el parámetro estará disponible en el diccionario request.GET. El parámetro puede faltar, por lo que debe utilizar requests.GET.get ( ‘categoría’) en lugar de requests.GET [ ‘categoría. El ex rendimientos Ninguno cuando no existe el parámetro, mientras que el último sería lanzar una excepción.

Nota: Asegúrese de que para validar los datos que se leen de las cadenas de consulta. Podría parecer que estos datos está bajo su control, ya que ha creado la URL de redirección.

En realidad, la redirección podría ser manipulado por el usuario y no debe ser de confianza, al igual que cualquier otra entrada del usuario. Sin validación adecuada, un atacante podría ser capaz de obtener acceso no autorizado. Códigos

de redireccionamiento especial

Django provee HTTP clases de respuesta de los códigos de estado 301 y 302. Los que deben cubrir la mayoría de los casos de uso, pero si alguna vez tiene que devolver los códigos de estado 303, 307, o 308, se puede crear fácilmente su propio la clase de respuesta. Simplemente subclase HttpResponseRedirectBase y sobrescribir el atributo status_code:

class HttpResponseTemporaryRedirect(HttpResponseRedirectBase):
status_code = 307

Alternativamente, se puede utilizar el método django.shortcuts.redirect () para crear un objeto de respuesta y cambiar el valor de retorno. Este enfoque tiene sentido cuando se tiene el nombre de una vista o una URL o un modelo que desea redirigir a:

def temporary_redirect_view(request):
response = redirect('success_view')
response.status_code = 307
return response

Nota: realidad, hay una tercera clase con un código de estado en la gama 3xx: HttpResponseNotModified, con la condición código 304. se indica que el URL contenido no ha cambiado y que el cliente puede utilizar una versión en caché.

Se podría argumentar que 304 Not Modified redirecciones de respuesta a la versión en caché de una URL, pero eso es un poco de un tramo. En consecuencia, se ya no aparece en la sección “redirección 3xx” de la norma HTTP.

Errores

redireccionamientos que se acaba de redirección no

La simplicidad de django.shortcuts.redirect () puede ser engañoso. La función en sí no realiza una redirección: simplemente devuelve un objeto de respuesta de redirección. Debe devolver este objeto respuesta de su punto de vista (o en un middleware). De lo contrario, sin redirección va a suceder.

Pero incluso si sabe que redirección simplemente llamando al () no es suficiente, es fácil introducir este error en una aplicación de trabajo a través de un simple refactorización. Aquí está un ejemplo para ilustrar que. de

Let asumen que usted está construyendo una tienda y tiene una vista que se encarga de mostrar un producto. Si el producto no existe, se redirige a la página de inicio:

def product_view(request, product_id):
try:
product = Product.objects.get(pk=product_id)
except Product.DoesNotExist:
return redirect('/')
return render(request, 'product_detail.html', {'product': product})

Ahora vamos a añadir un segundo objeto de críticas pantalla del cliente para un producto. También debe redirigir a la página de inicio para los productos no existentes, así como un primer paso, extraer esta funcionalidad de product_view () en un get_product_or_redirect función auxiliar ():

def get_product_or_redirect(product_id):
try:
return Product.objects.get(pk=product_id)
except Product.DoesNotExist:
return redirect('/')

def product_view(request, product_id):
product = get_product_or_redirect(product_id)
return render(request, 'product_detail.html', {'product': product})

Por desgracia, después de la refactorización, la redirección ya no funciona .

¿Se puede detectar el error? Mostrar / Ocultar

El resultado de redirección () se devuelve desde get_product_or_redirect (), pero product_view () no devuelve la misma. En su lugar, se pasa a la plantilla.

Dependiendo de cómo se utiliza la variable del producto en la plantilla product_detail.html, esto podría no resultar en un mensaje de error y simplemente mostrar los valores vacíos.

redireccionamientos que se acaba de parada no redireccionante

Cuando se trata de redirecciones, puede crear accidentalmente un bucle de redireccionamiento, por tener un retorno URL de una redirección que apunta al URL B que devuelve una redirección a URL A, y así sucesivamente. La mayoría de los clientes HTTP detectan este tipo de bucle de redireccionamiento y se mostrará un mensaje de error después de un número de peticiones.

Por desgracia, este tipo de error puede ser difícil de detectar porque todo se ve bien en el lado del servidor. A menos que sus usuarios se quejan de la cuestión, la única indicación de que algo no está bien es que usted tiene un número de peticiones de un cliente que todo el resultado de una respuesta de redirección en rápida sucesión, pero no hay respuesta con un estado 200 OK.

He aquí un ejemplo simple de un bucle de redireccionamiento:

def a_view(request):
return redirect('another_view')

def another_view(request):
return redirect('a_view')

Este ejemplo ilustra el principio, pero es demasiado simplista. Los bucles de redirección te vas a encontrar en la vida real son probablemente va a ser más difícil de detectar. Echemos un vistazo a un ejemplo más elaborado:

def featured_products_view(request):
featured_products = Product.objects.filter(featured=True)
if len(featured_products == 1):
return redirect('product_view', kwargs={'product_id': featured_products[0].id})
return render(request, 'featured_products.html', {'product': featured_products})

def product_view(request, product_id):
try:
product = Product.objects.get(pk=product_id, in_stock=True)
except Product.DoesNotExist:
return redirect('featured_products_view')
return render(request, 'product_detail.html', {'product': product})

featured_products_view () recupera todos los productos destacados, en otros casos las palabras de producto con el conjunto .featured en True. Si sólo existe un producto destacado, redirecciona directamente a product_view (). De lo contrario, se muestra una plantilla con el queryset featured_products.

El product_view parece familiar de la sección anterior, pero tiene dos diferencias menores:

  • La vista intenta obtener un producto que está en stock, indicado por tener .in_stock conjunto en True.
  • La vista se vuelve a dirigir a featured_products_view () si no hay producto en stock.

Esta lógica funciona bien hasta que su tienda se convierte en una víctima de su propio éxito y el producto ofrecido tiene actualmente sale de stock. Si se establece en False .in_stock pero se olvide de establecer .featured en False así, entonces cualquier visitante a su feature_product_view () ahora será atrapado en un bucle de redireccionamiento.

No hay manera a prueba de balas para evitar este tipo de error, sino un punto de partida bueno es comprobar si la vista está redirigiendo a los usos redirige a sí mismo. redirecciones

redirecciones permanentes son

Permanente

permanentes pueden ser como los malos tatuajes: podrían parecer una buena idea en el momento, pero una vez que te das cuenta de que eran un error, que puede ser muy difícil deshacerse de ellos.

Cuando un navegador recibe una respuesta de redirección permanente para una URL, almacena en caché esta respuesta de forma indefinida. Cualquier momento de solicitar la dirección de edad en el futuro, el navegador no se molesta en lo carga y se carga directamente a la nueva URL.

Puede ser muy difícil convencer a un navegador para cargar una URL que una vez que regresó una redirección permanente. Google Chrome es especialmente agresivo cuando se trata de redirecciones de almacenamiento en caché.

¿Por qué puede ser esto un problema?

Imagínese usted quiere construir una aplicación web con Django. Registre su dominio en myawesomedjangowebapp.com. Como primer paso, se instala una aplicación de blog en https://myawesomedjangowebapp.com/blog/ para construir una lista de correo de lanzamiento. página

de su sitio en https://myawesomedjangowebapp.com/ está todavía en construcción, por lo que redirecciona a https://myawesomedjangowebapp.com/blog/. Decide utilizar una redirección permanente porque has oído que redirecciones permanentes se almacenan en caché y caché de hacer las cosas más rápido y más rápido es mejor porque la velocidad es un factor para la clasificación en los resultados de búsqueda de Google.

Como resultado, usted no es sólo un gran desarrollador, sino también un escritor de talento. Su blog se hace popular, y su lista de correo lanzamiento crece. Después de un par de meses, su aplicación está lista. Ahora cuenta con una página de inicio brillante, y finalmente eliminar la redirección.

Usted envía un correo electrónico con un código de anuncio descuento especial a su lista de correo lanzamiento de tamaño considerable. De vuelta magra y esperar a que las notificaciones de registro para rodar en.

Para su horror, sus rellenos de buzón de mensajes de los visitantes confundido que quieren visitar su aplicación, pero siempre están siendo redirigidos a tu blog.

¿Qué ha pasado? Sus lectores del blog habían visitado https://myawesomedjangowebapp.com/ cuando la redirección a https://myawesomedjangowebapp.com/blog/ seguía activo. Debido a que era una redirección permanente, se almacena en caché en sus navegadores.

Cuando se hace clic en el enlace en su correo anuncio de lanzamiento, sus navegadores nunca se molestó en comprobar su nueva página de inicio y se dirigió directamente a su blog. En lugar de celebrar su exitoso lanzamiento, que está ocupado instruyendo a sus usuarios cómo jugar con chrome: // net-internals para restablecer la memoria caché de sus navegadores.

El carácter permanente de redirecciones permanentes también le puede morder mientras que el desarrollo de su ordenador local. rebobinado Vamos al momento en que se implementó que redirección permanente fatídico para myawesomedjangowebapp.com.

se inicia el servidor de desarrollo y http://127.0.0.1:8000/ abierta. Tal como se pretende, la aplicación redirige el navegador a http://127.0.0.1:8000/blog/. Satisfecho con su trabajo, se detiene el servidor de desarrollo e ir a comer.

enviar de regreso con el estómago lleno, listo para hacer frente a algunos de trabajo del cliente. El cliente quiere algunos cambios simples en su página web, de modo que cargue el proyecto del cliente e iniciar el servidor de desarrollo.

Pero espera, ¿qué está pasando aquí? La página principal está roto, ahora devuelve un 404! Debido a la caída de la tarde, que le lleva un tiempo darse cuenta de que estás siendo redirigido al http://127.0.0.1:8000/blog/, que no existe en el proyecto del cliente.

Para el navegador, no importa que el http://127.0.0.1:8000/ URL ahora sirve una aplicación completamente diferente. Lo único que importa es que el navegador que esta URL una vez en el pasado devolvió una redirección permanente a http://127.0.0.1:8000/blog/.

La lección de esta historia es que sólo se debe utilizar redirecciones permanentes en las direcciones URL que usted no tiene ninguna intención de volver a utilizar de nuevo. Hay un lugar para redirecciones permanentes, pero hay que ser conscientes de sus consecuencias.

Even if you’re confident that you really need a permanent redirect, it’s a good idea to implement a temporary redirect first and only switch to its permanent cousin once you’re 100% sure everything works as intended.

Unvalidated Redirects Can Compromise Security

From a security perspective, redirects are a relatively safe technique. An attacker cannot hack a website with a redirect. After all, a redirect just redirects to a URL that an attacker could just type in the address bar of their browser.

However, if you use some kind of user input, like a URL parameter, without proper validation as a redirect URL, this could be abused by an attacker for a phishing attack. This kind of redirect is called an open or unvalidated redirect.

There are legitimate use cases for redirecting to URL that is read from user input. A prime example is Django’s login view. It accepts a URL parameter next that contains the URL of the page the user is redirected to after login. To redirect the user to their profile after login, the URL might look like this:

https://myawesomedjangowebapp.com/login/?next=/profile/

Django does validate the next parameter, but let’s assume for a second that it doesn’t.

Without validation, an attacker could craft a URL that redirects the user to a website under their control, for example:

https://myawesomedjangowebapp.com/login/?next=https://myawesomedjangowebapp.co/profile/

The website myawesomedjangowebapp.co might then display an error message and trick the user into entering their credentials again.

The best way to avoid open redirects is to not use any user input when building a redirect URL.

If you cannot be sure that a URL is safe for redirection, you can use the function django.utils.http.is_safe_url() to validate it. The docstring explains its usage quite well:

is_safe_url(url, host=None, allowed_hosts=None, require_https=False)

Return True if the url is a safe redirection (i.e. it doesn’t point to a different host and uses a safe scheme).Always return False on an empty url.If require_https is True, only ‘https’ will be considered a valid scheme, as opposed to ‘http’ and ‘https’ with the default, False. (Source)

Let’s look at some examples.

A relative URL is considered safe:

>>> # Import the function first.
>>> from django.utils.http import is_safe_url
>>> is_safe_url('/profile/')
True

A URL pointing to another host is generally not considered safe:

>>> is_safe_url('https://myawesomedjangowebapp.com/profile/')
False

A URL pointing to another host is considered safe if its host is provided in allowed_hosts:

>>> is_safe_url('https://myawesomedjangowebapp.com/profile/',
... allowed_hosts={'myawesomedjangowebapp.com'})
True

If the argument require_https is True, a URL using the http scheme is not considered safe:

>>> is_safe_url('http://myawesomedjangowebapp.com/profile/',
... allowed_hosts={'myawesomedjangowebapp.com'},
... require_https=True)
False

Summary

This wraps up this guide on HTTP redirects with Django. Congratulations: you have now touched on every aspect of redirects all the way from the low-level details of the HTTP protocol to the high-level way of dealing with them in Django.

You learned how an HTTP redirect looks under the hood, what the different status codes are, and how permanent and temporary redirects differ. This knowledge is not specific to Django and is valuable for web development in any language.

You can now perform a redirect with Django, either by using the redirect response classes HttpResponseRedirect and HttpResponsePermanentRedirect, or with the convenience function django.shortcuts.redirect(). You saw solutions for a couple of advanced use cases and know how to steer clear of common pitfalls.

If you have any further question about HTTP redirects leave a comment below and in the meantime, happy redirecting!

References

  • Django documentation: django.http.HttpResponseRedirect
  • Django documentation: django.shortcuts.render()
  • Django documentation: django.views.generic.base.RedirectView
  • RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content – 6.4 Redirection 3xx
  • CWE-601: URL Redirection to Untrusted Site (‘Open Redirect’)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *