Django: come faccio a redirect un post e trasmettere i dati del post

Durante l’elaborazione di una richiesta POST nel file views.py di Django, a volte devo redirect a un altro URL. Questo URL che sto reindirizzando è gestito da un’altra funzione nello stesso file views.py di Django. C’è un modo per farlo e mantenere i dati POST originali?

AGGIORNAMENTO: ulteriori spiegazioni sul perché voglio farlo. Ho due app Web (chiamiamole AppA e AppB) che accettano i dati immessi in un campo di testo dall’utente. Quando l’utente fa clic su Invia, i dati vengono elaborati e vengono visualizzati i risultati dettagliati. AppA e AppB si aspettano tipi diversi di dati. A volte un utente pubblica erroneamente i dati di tipo AppB in AppA. Quando ciò accade, desidero reindirli a AppB e mostrare i risultati AppB o almeno farlo populare con i dati inseriti in AppA.

Anche:

AGGIORNAMENTO 2: Ho deciso che KISS è il miglior principio qui. Ho combinato le due app in una che rende le cose più semplici e robuste; Dovrei essere in grado di convincere il cliente che è il modo migliore per andare anche tu. Grazie per tutti gli ottimi feedback. Se avessi intenzione di mantenere due app come descritto, penso che le sessioni sarebbero il modo per farlo – grazie a Matthew J Morrison per averlo suggerito. Grazie a Dzida i suoi commenti mi hanno fatto pensare al design e alla semplificazione.

Se hai affrontato questo problema c’è una piccola possibilità che tu possa aver bisogno di rivedere i tuoi progetti.

Questa è una limitazione di HTTP che i dati POST non possono utilizzare con i reindirizzamenti.

Puoi descrivere cosa stai cercando di realizzare e forse allora possiamo pensare ad una soluzione pulita.

Se non si desidera utilizzare le sessioni come suggerito da Matteo, è ansible passare i parametri POST in GET alla nuova pagina (considerare alcune limitazioni come la sicurezza e la lunghezza massima dei parametri GET nella stringa di query).

AGGIORNA al tuo aggiornamento 🙂 Mi sembra strano che tu abbia 2 web app e quelle app usino un views.py (ho ragione?). In ogni caso, considera la possibilità di passare i dati da POST in GET alla visualizzazione corretta (nel caso in cui i dati non siano sensibili ovviamente).

Penso che probabilmente gestire questa situazione sarebbe come salvare i dati del post in sessione, quindi rimuoverlo quando non ne ho più bisogno. In questo modo posso accedere ai dati del post originale dopo un reindirizzamento anche se quel post è sparito.

Funzionerà per quello che stai cercando di fare?

Ecco un esempio di codice di ciò che sto suggerendo: (tieni presente che questo è un codice non testato)

 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 

Un’altra cosa da tenere a mente … se stai facendo questo e anche caricando file, non lo farei in questo modo.

È necessario utilizzare un reindirizzamento temporaneo HTTP 1.1 (307).

Sfortunatamente, Django redirect() e HTTPResponseRedirect (permanente) restituiscono solo un 301 o 302. Devi implementarlo tu stesso:

 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) 

Vedi anche il modulo django.http .

Modificare:

sulle versioni recenti di Django, cambia iri_to_uri import in:

 from django.utils.encoding import iri_to_uri 

usa il pacchetto di requests molto facile da implementare

 pip install requests 

quindi puoi chiamare qualsiasi URL con qualsiasi metodo e trasferire i dati

nelle tue viste importa le richieste

 import requests 

per inviare dati, segui il formato

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

per ottenere l’url assoluto nella vista django, usa

request.build_absolute_uri(reverse('view_name'))

Così appare il codice della vista di Django

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

dove r è l’object risposta con lo status_code e l’attributo del content . r.status_code fornisce il codice di stato (in caso di esito positivo sarà 200) e r.content fornisce il corpo della risposta. Esiste un metodo json ( r.json() ) che convertirà la risposta in formato json

richieste

requests.post

Basta chiamare la nuova vista dalla vecchia visualizzazione usando lo stesso object richiesta. Ovviamente non risulterà in un reindirizzamento come tale, ma se tutto ciò che ti interessa è il “trasferimento” dei dati da una vista all’altra, allora dovrebbe funzionare.
Ho testato il seguente frammento e funziona.

 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 

Con il rendering e il contesto puoi utilizzare con esso:

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

Puoi ricevere vars nel template:

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

Se si sta utilizzando un reindirizzamento dopo aver elaborato il POST in AppB , si può effettivamente fare a meno di chiamare il metodo AppB dal metodo AppA .

Un esempio:

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

Questo dovrebbe fornire un’esperienza trasparente per l’utente finale e il cliente che ha assunto probabilmente non conoscerà mai la differenza.

Se non stai reindirizzando dopo il POST, non sei preoccupato per i dati duplicati a causa del fatto che l’utente aggiorna la pagina?