Django:如何重定向帖子并传递帖子数据

时间:2010-06-11 15:40:34

标签: django

在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,他的评论让我想到了设计和简化。

8 个答案:

答案 0 :(得分:52)

如果遇到这样的问题,您可能需要修改设计。

这是HTTP限制,POST数据不能与重定向一起使用。

你能描述一下你想要完成什么,也许我们可以考虑一些简洁的解决方案。

如果你不想像Matthew建议的那样使用会话,你可以将GET中的POST参数传递给新页面(考虑一些限制,例如查询字符串中的GET参数的安全性和最大长度)。

更新到您的更新:) 我觉得你有两个网络应用程序,而那些应用程序使用一个views.py(我是对的吗?),这听起来很奇怪。无论如何,考虑将您的数据从GET中的POST传递到正确的视图(如果数据当然不敏感)。

答案 1 :(得分:46)

我认为我可能会处理这种情况的方法是在会话中保存帖子数据,然后在我不再需要时将其删除。这样,即使该帖子消失,我也可以在重定向后访问原始帖子数据。

这会对您要做的事情有用吗?

以下是我建议的代码示例:(请记住这是未经测试的代码)

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

要记住的另一件事是......如果你这样做并且还要上传文件,我不会这样做。

答案 2 :(得分:22)

您需要使用HTTP 1.1 Temporary Redirect(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 module

修改

在最近的Django版本上,将iri_to_uri导入更改为:

from django.utils.encoding import iri_to_uri

答案 3 :(得分:7)

使用requests package.Its非常容易实现

pip install requests

然后你可以用任何方法调用任何网址并传输数据

在您的视图中导入请求

import requests

发布数据,请按照格式

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

在django视图中获取绝对URL,使用

request.build_absolute_uri(reverse('view_name'))

因此django视图代码看起来像

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

其中r是具有status_codecontent属性的响应对象。 r.status_code提供状态代码(成功时为200),r.content给出响应正文。有一个json方法(r.json())将响应转换为json格式

requests

requests.post

答案 4 :(得分:2)

只需使用相同的请求对象从旧视图中调用新视图即可。 当然,它不会导致重定向,但如果你关心的只是转移'数据从一个视图到另一个视图,然后它应该工作 我测试了以下代码片段并且它可以正常工作。

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

答案 5 :(得分:1)

您可以使用呈现上下文

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

您可以在模板中收回变量:

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

答案 6 :(得分:1)

我最近遇到了类似的问题。

基本上,我有一个表单A,提交后会显示另一个表单B,其中包含一些结果和一个表单。提交B后,我想向用户显示一些警报,并使用户仅停留在B上。

我解决此问题的方法是在B的<output>字段中显示结果。

<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较小且不是动态表格的情况下有效。

答案 7 :(得分: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后没有重定向,那么您是否因为用户刷新页面而担心重复数据?