Al procesar una solicitud POST en el archivo Django views.py, a veces necesito redirigirla 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 los 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 sucede, quiero redirigirlos a AppB y mostrar los resultados de AppB o al menos llenarlos con los datos que ingresaron en AppA.
También:
El cliente quiere dos aplicaciones separadas en lugar de combinarlas en una sola.
No puedo mostrar el código porque pertenece a un cliente.
ACTUALIZACIÓN 2: He decidido que KISS es el mejor principio aquí. He combinado las dos aplicaciones en una que hace las cosas más simples y sólidas; Debería poder convencer al cliente de que también es la mejor manera de hacerlo. Gracias por todos los excelentes comentarios. Si tuviera que mantener dos aplicaciones como se describe, creo que las sesiones serían la forma de hacerlo, gracias a Matthew J Morrison por sugerir eso. Gracias a Dzida porque sus comentarios me hicieron pensar en el diseño y la simplificación.
id
en GET, y también tiene acceso a otros datos enviados por POST.Respuestas:
Si se enfrentó a tal problema, existe una pequeña posibilidad de que deba revisar sus diseños.
Esta es una restricción de HTTP que los datos POST no pueden ir con redirecciones.
¿Puede describir lo que está tratando de lograr y tal vez entonces podamos pensar en una buena solución?
Si no desea usar 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).
ACTUALIZAR a su actualización :) Me parece extraño que tenga 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).
fuente
Creo que la forma en que probablemente manejaría esta situación sería guardar los datos de la publicación en la sesión y luego eliminarlos 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 intentas 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á haciendo esto y también cargando archivos, yo no lo haría de esta manera.
fuente
Necesita utilizar un redireccionamiento temporal HTTP 1.1 (307).
Desafortunadamente, Django
redirect()
yHTTPResponseRedirect
(permanente) devuelven 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)
Consulte también el módulo django.http .
Editar:
en versiones recientes de Django, cambie la
iri_to_uri
importación a:from django.utils.encoding import iri_to_uri
fuente
requests
paquete de uso Es muy fácil de implementarpip install requests
entonces puedes 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 ve así
r = requests.post( request.build_absolute_uri(reverse('view_name')), data = {'key':'value'} )
donde
r
es el objeto de respuesta constatus_code
ycontent
atributo.r.status_code
da el código de estado (en caso de éxito, será 200) yr.content
da el cuerpo de la respuesta. Hay un método json (r.json()
) que convertirá la respuesta al formato jsonpeticiones
request.post
fuente
Simplemente llame a su nueva vista desde su vista anterior usando el mismo objeto de solicitud. Por supuesto, no resultará en 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
fuente
Puede usar render y contexto con él:
Render(request,"your template path", {'vad name' : var value}
Puede recibir vars en la plantilla:
fuente
Recientemente me enfrenté a un problema similar.
Básicamente tenía un formulario A, al enviarlo aparecerí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 renderizar 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 la forma B es pequeña y no tan dinámica.
fuente
Si está utilizando una redirección después de procesar el POST
AppB
, puede salirse con la suya llamando alAppB
método desde elAppA
método.Un ejemplo:
def is_appa_request(request): ## do some magic. return False or True is_appb_request = is_appa_request def AppA(request): if is_appb_request(request): return AppB(request) ## Process AppA. return HttpResponseRedirect('/appa/thank_you/') def AppB(request): if is_appa_request(request): return AppA(request) ## Process AppB. return HttpResponseRedirect('/appb/thank_you/')
Esto debería generar una experiencia transparente para el usuario final, y es probable que el cliente que lo contrató nunca sepa la diferencia.
Si no está redireccionando después del POST, ¿no le preocupa la duplicación de datos debido a que el usuario actualiza la página?
fuente
pk
de la nueva entrada cuando redirija. # 2, almacene los datos en elcache
backend y vuelva a pasar la clave. # 3, guárdelo en la sesión. Cualquiera de estos es perfectamente normal para una aplicación web, incluso si es temporal. Si los datos del formulario no son triviales de analizar, también haría que el sistema fuera más rápido si la salida ya estaba almacenada en caché.