Podczas przetwarzania żądania POST w pliku Django views.py, czasami muszę przekierować go do innego adresu URL. Ten adres URL, do którego przekierowuję, jest obsługiwany przez inną funkcję w tym samym pliku Django views.py. Czy można to zrobić i zachować oryginalne dane POST?
UPDATE: Więcej wyjaśnień, dlaczego chcę to zrobić. Mam dwie aplikacje internetowe (nazwijmy je AppA i AppB), które akceptują dane wprowadzone w polu tekstowym przez użytkownika. Gdy użytkownik kliknie przycisk Prześlij, dane są przetwarzane i wyświetlane są szczegółowe wyniki. AppA i AppB oczekują różnych typów danych. Czasami użytkownik omyłkowo wysyła dane typu AppB do AppA. Kiedy tak się stanie, chcę przekierować ich do AppB i pokazać wyniki AppB lub przynajmniej wypełnić je danymi, które wprowadzili do AppA.
Również:
Klient chce mieć dwie oddzielne aplikacje, zamiast łączyć je w jedną.
Nie mogę pokazać kodu, ponieważ należy on do klienta.
UPDATE 2: Zdecydowałem, że KISS jest tutaj najlepszą zasadą. Połączyłem te dwie aplikacje w jedną, dzięki czemu wszystko jest prostsze i solidniejsze; Powinienem być w stanie przekonać klienta, że to też najlepszy sposób. Dzięki za wszystkie wspaniałe opinie. Gdybym miał zachować dwie aplikacje zgodnie z opisem, myślę, że sesje byłyby sposobem na to - dzięki Matthew J Morrisonowi za zasugerowanie tego. Dzięki Dzidzie, ponieważ jego uwagi skłoniły mnie do zastanowienia się nad projektem i uproszczeniem.
id
GET, a także ma dostęp do innych danych przesłanych przez POST.Odpowiedzi:
Jeśli napotkałeś taki problem, istnieje niewielka szansa, że będziesz musiał zrewidować swoje projekty.
Jest to ograniczenie protokołu HTTP, którego dane POST nie mogą przejść z przekierowaniami.
Czy możesz opisać, co próbujesz osiągnąć, a może wtedy pomyśleć o jakimś zgrabnym rozwiązaniu.
Jeśli nie chcesz używać sesji, jak sugerował Matthew, możesz przekazać parametry POST w GET do nowej strony (rozważ pewne ograniczenia, takie jak bezpieczeństwo i maksymalna długość parametrów GET w ciągu zapytania).
ZAKTUALIZUJ swoją aktualizację :) Dziwnie mi się wydaje, że masz 2 aplikacje internetowe i te aplikacje używają jednego views.py (mam rację?). W każdym razie rozważ przekazanie danych z POST w GET do odpowiedniego widoku (oczywiście w przypadku, gdy dane nie są wrażliwe).
źródło
Myślę, że prawdopodobnie poradziłbym sobie z tą sytuacją, gdyby zapisał dane posta w sesji, a następnie usunął go, gdy już go nie potrzebuję. W ten sposób mogę uzyskać dostęp do oryginalnych danych postu po przekierowaniu, mimo że ten post zniknął.
Czy to zadziała w przypadku tego, co próbujesz zrobić?
Oto przykład kodu tego, co sugeruję: (pamiętaj, że jest to kod nieprzetestowany)
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
Jeszcze jedna rzecz, o której należy pamiętać ... jeśli robisz to i przesyłasz pliki, nie zrobiłbym tego w ten sposób.
źródło
Musisz użyć tymczasowego przekierowania HTTP 1.1 (307).
Niestety, Django
redirect()
iHTTPResponseRedirect
(na stałe) zwracają tylko 301 lub 302. Musisz to zaimplementować samodzielnie: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)
Zobacz także moduł django.http .
Edytować:
w najnowszych wersjach Django zmień
iri_to_uri
import na:from django.utils.encoding import iri_to_uri
źródło
użyj
requests
pakietu.Jest bardzo łatwy do wdrożeniapip install requests
wtedy możesz wywoływać adresy URL dowolną metodą i przesyłać dane
w Twoich widokach żądań importu
import requests
aby publikować dane, postępuj zgodnie z formatem
r = requests.post('http://yourdomain/path/', data = {'key':'value'})
aby uzyskać bezwzględny adres URL w widoku django, użyj
request.build_absolute_uri(reverse('view_name'))
Tak wygląda kod widoku django
r = requests.post( request.build_absolute_uri(reverse('view_name')), data = {'key':'value'} )
gdzie
r
jest obiektem odpowiedzi z atrybutemstatus_code
icontent
.r.status_code
podaje kod statusu (w przypadku pomyślnego zakończenia będzie to 200) ir.content
treść odpowiedzi. Istnieje metoda json (r.json()
), która konwertuje odpowiedź na format jsonupraszanie
request.post
źródło
Po prostu wywołaj nowy widok ze starego widoku, używając tego samego obiektu żądania. Oczywiście nie spowoduje to przekierowania jako takiego, ale jeśli wszystko, na czym Ci zależy, to „przesyłanie” danych z jednego widoku do drugiego, to powinno działać.
Przetestowałem następujący fragment kodu i działa.
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
źródło
Możesz z nim użyć renderowania i kontekstu :
Render(request,"your template path", {'vad name' : var value}
Możesz otrzymać vars w szablonie:
źródło
Ostatnio miałem podobny problem.
Zasadniczo miałem formularz A, po przesłaniu go pojawił się inny formularz B, który zawiera niektóre wyniki + formularz. Po przesłaniu B chciałem wyświetlić alert użytkownikowi i zachować go tylko na B.
Sposób, w jaki to rozwiązałem, polega na wyświetleniu wyników w
<output>
polu, w B.<output name="xyz" value="xyz">{{xyz}}</output>
I użyłem tego samego widoku dla A-> B i B-> B. Teraz musiałem tylko rozróżnić, czy żądanie pochodzi z A czy B i odpowiednio wyrenderować.
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})
Ale to działa tylko wtedy, gdy forma B jest mała i nie tak dynamiczna.
źródło
Jeśli używasz przekierowania po przetworzeniu POST do
AppB
, możesz faktycznie uciec z wywołaniemAppB
metody zAppA
metody.Przykład:
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/')
Powinno to zapewnić przejrzystość dla użytkownika końcowego, a klient, który Cię zatrudnił, prawdopodobnie nigdy nie zauważy różnicy.
Jeśli nie przekierowujesz po POST, czy nie martwisz się zduplikowanymi danymi z powodu odświeżania strony przez użytkownika?
źródło
pk
nowy wpis podczas przekierowywania. # 2, zapisz dane nacache
zapleczu i ponownie przekaż klucz. # 3, zapisz go w sesji. Każda z nich jest całkowicie normalna dla aplikacji internetowej, nawet jeśli jest tymczasowa. Jeśli dane formularza są nietrywialne do przeanalizowania, przyspieszyłoby to również system, gdyby dane wyjściowe były już buforowane.