Cómo redirigir con datos de publicación (Django)

9 minutos de lectura

avatar de usuario
FunLovinCoder

Al procesar una solicitud POST en el archivo Django views.py, a veces necesito redirigirlo a otra URL. Esta URL a la que estoy redirigiendo es manejada por otra función en el mismo archivo Django views.py. ¿Hay alguna forma de hacer esto y mantener los datos POST originales?

ACTUALIZACIÓN: Más explicación de por qué quiero hacer esto. Tengo dos aplicaciones web (llamémoslas AppA y AppB) que aceptan datos ingresados ​​en un campo de texto por el usuario. Cuando el usuario hace clic en enviar, los datos se procesan y se muestran resultados detallados. AppA y AppB esperan diferentes tipos de datos. A veces, un usuario publica por error datos de tipo AppB en AppA. Cuando esto suceda, quiero redirigirlos a la aplicación B y mostrar los resultados de la aplicación B o al menos llenarlos con los datos que ingresaron en la aplicación A.

También:

  • El cliente quiere dos aplicaciones separadas en lugar de combinarlas en una sola.

  • No puedo mostrar el código ya que pertenece a un cliente.

ACTUALIZACIÓN 2: He decidido que KISS es el mejor principio aquí. He combinado las dos aplicaciones en una que simplifica y fortalece las cosas; También debería poder convencer al cliente de que es la mejor manera de hacerlo. Gracias por todos los excelentes comentarios. Si iba a mantener dos aplicaciones como se describe, creo que las sesiones serían la forma de hacerlo. Gracias a Matthew J Morrison por sugerirlo. Gracias a Dzida porque sus comentarios me hicieron pensar en el diseño y la simplificación.

  • ¿Realmente necesita enviar una redirección al cliente, o es algo que se puede hacer simplemente llamando a una función y pasándole todos los datos de la publicación?

    – Matthew J. Morrison

    11 de junio de 2010 a las 15:44

  • Necesito cambiar la URL en el navegador del cliente, por lo que esta es la única forma en que puedo hacerlo.

    – FunLovinCoder

    11 de junio de 2010 a las 15:45


  • ¿Y no puede simplemente hacer todo el procesamiento con los datos de la publicación primero y luego redirigir después del hecho?

    – Matthew J. Morrison

    11 de junio de 2010 a las 15:46

  • Tengo una situación similar, pero los datos publicados en POST coinciden o no con los datos existentes. Si coincide, obtengo la identificación de esos datos, luego paso esa identificación al script a través de la variable GET en la redirección. También guardo los datos POST en SESSION. Ahora la página redirigida carga los datos a los que hace referencia el id en GET, y también tiene acceso a otros datos enviados por POST.

    -Buttle Butkus

    2 de enero de 2014 a las 23:34

avatar de usuario
dzida

Si se enfrentó a ese problema, existe una pequeña posibilidad de que necesite revisar sus diseños.

Esta es una restricción de HTTP de que los datos POST no pueden ir con redireccionamientos.

¿Puede describir lo que está tratando de lograr y tal vez entonces podamos pensar en una buena solución?

Si no desea utilizar las sesiones como sugirió Matthew, puede pasar los parámetros POST en GET a la nueva página (considere algunas limitaciones, como la seguridad y la longitud máxima de los parámetros GET en la cadena de consulta).

ACTUALIZA tu actualización 🙂 Me parece extraño que tengas 2 aplicaciones web y esas aplicaciones usen una views.py (¿verdad?). De todos modos, considere pasar sus datos de POST en GET a la vista adecuada (en caso de que los datos no sean confidenciales, por supuesto).

  • Puedo ver lo que él está tratando de hacer podría ser válido si está tratando de manejar un inicio de sesión caducado que obligará a un usuario a iniciar sesión después de enviar un formulario… en ese caso, querrá conservar el datos que se enviaron y no obligar al usuario a volver a ingresar todo después de completar la pantalla de inicio de sesión.

    – Matthew J. Morrison

    11 de junio de 2010 a las 16:43

  • No estoy seguro de si entendí el punto, pero en este caso, la operación de inicio de sesión se puede realizar mediante la primera vista con una pequeña modificación del código y sin realizar redireccionamientos innecesarios. Sería genial leer el código existente para hacer consejos más precisos.

    – dzida

    11 de junio de 2010 a las 16:53

  • Estoy diciendo que si envía un formulario y no ha iniciado sesión, será redirigido a un formulario de inicio de sesión… en ese escenario, perderá lo que haya enviado. Estoy de acuerdo en poder ver algún código existente.

    – Matthew J. Morrison

    11 de junio de 2010 a las 17:02

  • No depende de usted decidir si el caso de uso es válido o no, me enfrento a la misma situación para la cual una redirección con POST nuevo es la solución perfecta en términos de simplicidad y modularidad.

    – Rabih Kodeih

    18/10/2012 a las 20:53

avatar de usuario
Mateo J Morrison

Creo que probablemente manejaría esta situación guardando los datos de la publicación en la sesión y luego eliminándolos cuando ya no los necesite. De esa manera, puedo acceder a los datos de la publicación original después de una redirección aunque esa publicación ya no esté.

¿Funcionará eso para lo que estás tratando de hacer?

Aquí hay una muestra de código de lo que sugiero: (tenga en cuenta que este es un código no probado)

def some_view(request):
    #do some stuff
    request.session['_old_post'] = request.POST
    return HttpResponseRedirect('next_view')

def next_view(request):
    old_post = request.session.get('_old_post')
    #do some stuff using old_post

Otra cosa a tener en cuenta… si estás haciendo esto y también subiendo archivos, no lo haría de esta manera.

  • Nunca he usado sesiones, pero le echaré un vistazo gracias.

    – FunLovinCoder

    11 de junio de 2010 a las 15:50

  • esta no es la mejor práctica, pero aún ayuda. Supongo que para este número no conseguiremos nada más bonito.

    –Guilherme David da Costa

    10 mayo 2013 a las 19:14

  • @GuilhermeDaviddaCosta ¿por qué dice que no es la mejor práctica? ¿Puedes darnos una pista?

    -Buttle Butkus

    02/01/2014 a las 23:32

  • porque no me parece muy buena idea almacenar demasiados datos en sesión. Pero como también he dicho, no se me ocurre nada más bonito.

    –Guilherme David da Costa

    16 de enero de 2014 a las 8:40

  • Bueno, eso depende de dónde esté almacenando su sesión. Últimamente, he estado viendo personas que usan un servidor completo con Memcached para sesiones y equilibran la carga (usando round robin) en cada solicitud. No quiero darte un consejo que no puedo defender, pero guardaría el archivo como temporal y obtendría solo un enlace para él en la sesión. Parece que nadie se está quedando sin RAM en estos días.

    –Guilherme David da Costa

    10 de marzo de 2014 a las 17:24

avatar de usuario
lloeki

Necesitas usar un Redirección temporal HTTP 1.1 (307).

Desafortunadamente, Django redirect() y HTTPResponseRedirect

(permanente) devuelve solo un 301 o 302. Tienes que implementarlo tú mismo:

from django.http import HttpResponse, iri_to_uri
class HttpResponseTemporaryRedirect(HttpResponse):
    status_code = 307

    def __init__(self, redirect_to):
        HttpResponse.__init__(self)
        self['Location'] = iri_to_uri(redirect_to)

Véase también el módulo django.http.

Editar:

en versiones recientes de Django, cambie iri_to_uri importar a:

from django.utils.encoding import iri_to_uri

  • Las versiones más nuevas de Django tienen una redirección permanente HttpResponsePermanentRedirect pero no estoy seguro de si resuelve el problema original docs.djangoproject.com/en/dev/ref/request-response/…

    – Pepito Grillo

    12 de diciembre de 2013 a las 21:44

  • ¿Esto conserva los datos POST a través de la redirección?

    – dfrankow

    2 de septiembre de 2021 a las 19:28

avatar de usuario
Aneesh RS

usar requests paquete. Es muy fácil de implementar

pip install requests

entonces puede llamar a cualquier URL con cualquier método y transferir datos

en sus vistas solicitudes de importación

import requests

para publicar datos, siga el formato

r = requests.post('http://yourdomain/path/', data = {'key':'value'})

para obtener la url absoluta en la vista de django, use

request.build_absolute_uri(reverse('view_name'))

Por lo tanto, el código de vista de Django se parece a

r = requests.post(
            request.build_absolute_uri(reverse('view_name')), 
            data = {'key':'value'}
    )

dónde r es el objeto de respuesta con status_code y content atributo.
r.status_code da el código de estado (en caso de éxito será 200) y r.content da el cuerpo de la respuesta. Hay un método json (r.json()) que convertirá la respuesta al formato json

peticiones

solicitudes.post

Simplemente llame a su nueva vista desde su vista anterior usando el mismo objeto de solicitud. Por supuesto, no dará como resultado una redirección como tal, pero si todo lo que le importa es “transferir” datos de una vista a otra, entonces debería funcionar.
Probé el siguiente fragmento y funciona.

from django.views.generic import View

class MyOldView(View):
    def post(self, request):
        return MyNewView().post(request)

class MyNewView(View):
    def post(self, request):
        my_data = request.body
        print "look Ma; my data made it over here:", my_data

  • Esta es una buena idea, pero no cambia la URL en el navegador del usuario. Parece que OP quiere reenviar a una nueva URL.

    – dfrankow

    2 sep 2021 a las 19:27

  • Eso funcionó, gracias. Sin embargo, self.request se perdió en la nueva vista, así que eso fue lo que hice: new_view = MyNewView(); new_view.request = request; new_view.post(request)

    – Mario Orlando

    5 de junio a las 8:59

avatar de usuario
Omid Reza

Puedes usar prestar y contexto con con eso:

Render(request,"your template path",        {'vad name' : var value}

Puede recibir vars en la plantilla:

{% If var name %}
 {{ var name }}
{% endif %}

  • Esta es una buena idea, pero no cambia la URL en el navegador del usuario. Parece que OP quiere reenviar a una nueva URL.

    – dfrankow

    2 sep 2021 a las 19:27

  • Eso funcionó, gracias. Sin embargo, self.request se perdió en la nueva vista, así que eso fue lo que hice: new_view = MyNewView(); new_view.request = request; new_view.post(request)

    – Mario Orlando

    5 de junio a las 8:59

avatar de usuario
rkp768

Me enfrenté a un problema similar recientemente.

Básicamente, tenía un formulario A, al enviarlo aparecía otro formulario B, que contiene algunos resultados + un formulario. Al enviar B, quería mostrar alguna alerta al usuario y mantener al usuario solo en B.

La forma en que resolví esto es mostrando los resultados en un <output> campo, en B.

<output name="xyz" value="xyz">{{xyz}}</output>

Y usé la misma vista para A->B y B->B. Ahora solo tenía que distinguir si la solicitud proviene de A o B y procesarla en consecuencia.

def view1(request):
    if "xyz" in request.POST:
        # request from B
        # do some processing
        return render(request, 'page.html', {"xyz":request.POST["xyz"]})
    else:
        # request from A
        res = foo() # some random function
        return render(request, 'page.html', {"xyz":res})

Pero esto solo funciona si el formulario B es pequeño y no tan dinámico.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad