在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,他的评论让我想到了设计和简化。
答案 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_code
和content
属性的响应对象。
r.status_code
提供状态代码(成功时为200),r.content
给出响应正文。有一个json方法(r.json()
)将响应转换为json格式
答案 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后没有重定向,那么您是否因为用户刷新页面而担心重复数据?