Django : 게시물을 리디렉션하고 게시물 데이터를 전달하는 방법


80

Django views.py 파일에서 POST 요청을 처리 할 때 가끔 다른 URL로 리디렉션해야합니다. 리디렉션중인이 URL은 동일한 Django views.py 파일의 다른 함수에 의해 처리됩니다. 이 작업을 수행하고 원래 POST 데이터를 유지하는 방법이 있습니까?

업데이트 : 내가 이것을하고 싶은 이유에 대한 더 많은 설명. 사용자가 텍스트 필드에 입력 한 데이터를 받아들이는 두 개의 웹 앱 (AppA 및 AppB라고합시다)이 있습니다. 사용자가 제출을 클릭하면 데이터가 처리되고 자세한 결과가 표시됩니다. AppA와 AppB는 서로 다른 유형의 데이터를 기대합니다. 때때로 사용자가 실수로 AppB 유형 데이터를 AppA에 게시합니다. 이런 일이 발생하면 AppB로 리디렉션하고 AppB 결과를 표시하거나 적어도 AppA에 입력 한 데이터로 채우고 싶습니다.

또한:

  • 클라이언트는 두 개의 개별 앱을 하나로 결합하기를 원합니다.

  • 클라이언트 소유이므로 코드를 표시 할 수 없습니다.

업데이트 2 : 나는 KISS가 여기서 최고의 원칙이라고 결정했습니다. 두 앱을 하나로 결합하여 더 간단하고 강력하게 만들었습니다. 나는 고객에게 그것이 최선의 방법이라고 확신 할 수 있어야합니다. 모든 훌륭한 피드백에 감사드립니다. 설명 된대로 두 개의 앱을 유지하려는 경우 세션이이를 수행하는 방법이라고 생각합니다. 제안 해 주신 Matthew J Morrison에게 감사드립니다. Dzida의 코멘트 덕분에 디자인과 단순화에 대해 생각하게되었습니다.


정말로 클라이언트에 리디렉션을 보내야합니까? 아니면 함수를 호출하고 모든 포스트 데이터를 전달함으로써 수행 할 수있는 일입니까?
Matthew J Morrison

클라이언트의 브라우저에서 URL을 변경해야하므로 이것이 내가 할 수있는 유일한 방법입니다.
FunLovinCoder 2010 년

먼저 포스트 데이터로 모든 처리를 수행 한 다음 사실 후에 리디렉션 할 수 없습니까?
Matthew J Morrison

비슷한 상황이 있지만 POST 데이터가 기존 데이터와 일치하거나 일치하지 않습니다. 일치하면 해당 데이터의 ID를 얻은 다음 리디렉션의 GET 변수를 통해 해당 ID를 스크립트에 전달합니다. 또한 SESSION에 POST 데이터를 저장합니다. 이제 리디렉션 된 페이지 id는 GET에서 참조하는 데이터를로드하고 POST에서 제출 한 다른 데이터에도 액세스 할 수 있습니다.
Buttle Butkus 2014 년

답변:


57

이러한 문제에 직면했다면 디자인을 수정해야 할 가능성이 약간 있습니다.

이것은 POST 데이터가 리디렉션과 함께 이동할 수없는 HTTP의 제한 사항입니다.

달성하려는 작업을 설명해 주시면 멋진 해결책에 대해 생각할 수있을 것입니다.

Matthew가 제안한대로 세션을 사용하지 않으려면 GET의 POST 매개 변수를 새 페이지로 전달할 수 있습니다 (보안 및 쿼리 문자열에서 GET 매개 변수의 최대 길이와 같은 일부 제한 사항을 고려하십시오).

업데이트 업데이트 :) 2 개의 웹 앱이 있고 해당 앱이 하나의 views.py를 사용한다는 것이 이상하게 들립니다 (맞습니까?). 어쨌든 GET의 POST에서 적절한보기로 데이터를 전달하는 것을 고려하십시오 (물론 데이터가 민감하지 않은 경우).


2
사용자가 양식을 제출 한 후 강제로 로그인하도록하는 만료 된 로그인을 처리하려는 경우 그가하려는 작업이 유효 할 수 있음을 알 수 있습니다 ...이 경우 그는 제출 된 데이터이며 사용자가 로그인 화면을 완료 한 후 모든 것을 다시 입력하도록 강요하지 않습니다.
Matthew J Morrison

요점을 얻었는지 확실하지 않지만이 경우에는 코드를 거의 수정하지 않고 불필요한 리디렉션없이 첫 번째보기로 로그인 작업을 수행 할 수 있습니다. 보다 정확한 조언을하기 위해 기존 코드를 읽는 것이 좋을 것입니다.
dzida

양식을 제출하고 로그인하지 않은 경우 로그인 양식으로 리디렉션됩니다.이 시나리오에서는 제출 한 내용을 잃게됩니다. 기존 코드를 볼 수 있다는 것에 동의합니다.
Matthew J Morrison

1
유스 케이스가 유효한지 여부를 결정하는 것은 귀하에게 달려 있지 않습니다. 단순성과 모듈성 측면에서 새로운 POST를 사용한 리디렉션이 완벽한 솔루션 인 동일한 상황에 직면했습니다.
Rabih Kodeih

54

이 상황을 처리하는 방법은 세션에 게시물 데이터를 저장 한 다음 더 이상 필요하지 않을 때 제거하는 것입니다. 이렇게하면 해당 게시물이 사라진 경우에도 리디렉션 후 원래 게시물 데이터에 액세스 할 수 있습니다.

그것이 당신이하려는 일에 효과가 있습니까?

다음은 내가 제안하는 코드 샘플입니다. (테스트되지 않은 코드임을 명심하십시오)

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

명심해야 할 또 한 가지 사항은 ...이 작업을 수행하고 파일을 업로드하는 경우에는 이렇게하지 않을 것입니다.


1
세션을 사용한 적이 없지만 감사합니다.
FunLovinCoder 2010 년

1
이것은 모범 사례는 아니지만 여전히 도움이됩니다. 이 문제에 대해 우리는 더 예쁜 것을 얻지 못할 것이라고 생각합니다.
Guilherme David da Costa

@GuilhermeDaviddaCosta 왜 이것이 모범 사례가 아니라고 말합니까? 힌트를 주실 수 있습니까?
Buttle Butkus 2014 년

세션에 너무 많은 데이터를 저장하는 것은별로 좋은 생각이 아니기 때문입니다. 하지만 말했듯이 더 예쁜 것이 생각 나지 않습니다.
Guilherme 데이비드 다 코스타

4
음, 세션을 저장하는 위치에 따라 다릅니다. 최근에는 세션 및 모든 요청에 ​​대해로드 밸런스 (라운드 로빈 사용)를 위해 memcached가있는 전체 서버를 사용하는 사람들을 보았습니다. 내가 참을 수없는 조언을하고 싶지는 않지만 파일을 임시로 저장하고 세션에서 링크 만 얻을 수 있습니다. 요즘 아무도 숫양이 부족한 것 같습니다.
Guilherme David da Costa

23

HTTP 1.1 임시 리디렉션 (307) 을 사용해야합니다 .

불행히도 Django redirect()HTTPResponseRedirect (영구)는 301 또는 302 만 반환합니다. 직접 구현해야합니다.

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)

django.http 모듈 도 참조하십시오 .

편집하다:

최신 Django 버전에서 iri_to_uri가져 오기를 다음으로 변경하십시오 .

from django.utils.encoding import iri_to_uri

최신 버전의 Django에는 영구 리디렉션 HttpResponsePermanentRedirect가 있지만 원래 문제가 해결되는지 확실하지 않습니다. docs.djangoproject.com/en/dev/ref/request-response/…
JiminyCricket 2013

9

requests패키지를 사용하십시오. 구현하기가 매우 쉽습니다.

pip install requests

그런 다음 모든 방법으로 모든 URL을 호출하고 데이터를 전송할 수 있습니다.

보기 가져 오기 요청에서

import requests

데이터를 게시하려면 형식을 따르십시오.

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

장고보기에서 절대 URL을 얻으려면

request.build_absolute_uri(reverse('view_name'))

따라서 장고 뷰 코드는 다음과 같습니다.

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

및 속성 r이있는 응답 객체는 어디에 있습니까 ? 상태 코드 (성공시 200이 됨)를 제공하고 응답 본문을 제공합니다. 응답을 json 형식으로 변환 하는 json method ( )가 있습니다.status_codecontentr.status_coder.contentr.json()

요청

requests.post


4

동일한 요청 객체를 사용하여 이전 뷰에서 새 뷰를 호출하기 만하면됩니다. 물론 리디렉션이 발생하지는 않지만 한보기에서 다른보기로 데이터를 '전송'하는 것이 중요하다면 작동합니다.
다음 스 니펫을 테스트했으며 작동합니다.

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

1

렌더링컨텍스트 를 함께 사용할 수 있습니다 .

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

템플릿에서 변수를받을 수 있습니다.

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

1

최근 비슷한 문제에 직면했습니다.

기본적으로 나는 양식 A를 가지고 있었고, 제출하면 다른 양식 B가 표시되며 일부 결과 + 양식이 포함됩니다. B를 제출할 때 사용자에게 경고를 표시하고 사용자를 B에만 유지하고 싶었습니다.

이 문제를 해결 한 방법 <output>은 B 의 필드에 결과를 표시하는 것 입니다.

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

그리고 A-> B와 B-> B에 대해 동일한 뷰를 사용했습니다. 이제 요청이 A 또는 B에서 오는지 구별하고 그에 따라 렌더링해야합니다.

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})

그러나 이것은 B 형이 작고 동적이 아닌 경우에만 작동합니다.


0

에 대한 POST를 처리 한 후 리디렉션을 사용하는 경우 AppB실제로 AppB메서드에서 메서드를 호출하지 않아도됩니다 AppA.

예 :

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

이는 최종 사용자에게 투명한 경험을 제공해야하며 귀하를 고용 한 고객은 그 차이를 결코 알지 못할 것입니다.

POST 후 리디렉션하지 않는 경우 사용자가 페이지를 새로 고쳐 중복 데이터가 걱정되지 않습니까?


이와 같은 간단한 솔루션이 효과가 있다면 좋을 것입니다. 그러나 데이터 처리 후 자세한 결과를 표시해야합니다. (Matthew J Morrison이 제안한대로) 세션이 필요하지 않습니까?
FunLovinCoder

1
세 가지 방법 중 하나로 할 수 있습니다. # 1, 데이터를 데이터베이스에 저장하고 pk리디렉션 할 때 새 항목을 전달합니다 . # 2, 데이터를 cache백엔드 에 저장 하고 키를 다시 전달합니다. # 3, 세션에 저장하십시오. 웹 앱이 일시적인 경우에도 이러한 작업은 완벽하게 정상입니다. 양식 데이터가 파싱하기에 사소하지 않은 경우 출력이 이미 캐시 된 경우 시스템 속도도 빨라집니다.
Jack M.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.