我正在开发一个Django设置,我可以在其中收到一个包含查询字符串的URL作为GET的一部分。我希望能够处理查询字符串中提供的数据,并返回针对该数据调整但不包含URL中的查询字符串的页面。
通常我会使用reverse()
,但我不确定如何在这种情况下应用它。以下是具体情况:
示例网址 .../test/123/?list_options=1&list_options=2&list_options=3
urls.py
urlpatterns = patterns('',
url(r'test/(P<testrun_id>\d+)/'), views.testrun, name='testrun')
)
views.py
def testrun(request, testrun_id):
if 'list_options' in request.GET.keys():
lopt = request.GET.getlist('list_options')
:
:
[process lopt list]
:
:
:
:
[other processing]
:
:
context = { ...stuff... }
return render(request, 'test_tracker/testview.html', context)
当处理示例URL时,Django将返回我想要的页面,但URL仍然包含末尾的查询字符串。剥离不需要的查询字符串的标准方法是使用return HttpResponseRedirect(reverse('testrun', args=(testrun_id,)))
返回testrun函数。但是,如果我在这里这样做,那么我将通过testrun
函数获得无限循环。此外,我不确定原始请求中的list_options数据在重定向之后是否仍然可用,因为它已从URL中删除。
我该如何解决这个问题?我可以看到将list_options变量的解析移到一个单独的函数中以避免无限递归可能是有意义的,但是如果我这样做的话,我担心它会从请求中丢失list_options数据。有没有一种巧妙的方法可以同时从URL的末尾删除查询字符串并在一个地方返回我想要的页面,这样我就可以避免将各个单独的内容分成多个函数?
编辑:一些额外的背景,因为有几个“你为什么要这样做?”查询。我正在设计的网站是报告我正在处理的软件的各种测试结果。这个特定页面用于报告单个测试的结果,通常我会从更大的测试列表链接到它。
list_options
数组是一种指定我刚刚来自的列表中的其他测试的方法。这允许我使用其他相关测试填充下拉菜单,以便我可以轻松地在它们之间切换。
因此,我很容易最终传递15-20个不同的值并创建大量的URL,我想避免这些。如果我没有在URL中建议任何其他内容,那么该页面将设计为具有一组默认的其他测试以填充相关菜单,因此如果我删除list_options
,这不是什么大问题。如果用户希望直接返回页面,他将不关心列表中的其他测试,因此如果该信息不可用则不会出现问题。
答案 0 :(得分:2)
首先要小心谨慎。出于各种原因,这可能不是一个好主意:
.../link?q=bar&order=foo
将过滤一些搜索结果,并按特定顺序对结果进行排序。如果您将自动删除查询字符串,那么您将有效地禁止用户为特定搜索查询添加书签。如果您仍想实现这一目标,最简单的方法之一就是使用会话。我们的想法是,当存在查询字符串时,将其内容保存到会话中,然后在没有查询字符串时检索它。例如:
def testrun(request, testrun_id):
# save the get data
if request.META['QUERY_STRING']:
request.session['testrun_get'] = request.GET
# the following will not have querystring hence no infinite loop
return HttpResponseRedirect(reverse('testrun', args=(testrun_id,)))
# there is no querystring so retreive it from session
# however someone could visit the url without the querystring
# without visiting the querystring version first hence
# you have to test for it
get_data = request.session.get('testrun_get', None)
if get_data:
if 'list_options' in get_data.keys():
...
else:
# do some default option
...
context = { ...stuff... }
return render(request, 'test_tracker/testview.html', context)
这应该可行,但它可以很容易地破解,并且没有办法轻易修复它。这应该说明上面的第二个子弹。例如,假设用户想要并排比较两个搜索查询。因此,他会尝试在同一浏览器的不同标签中访问.../link?q=bar&order=foo
和`.../link?q=cat&order=dog
。到目前为止一切都很好,因为每个页面都会打开正确的结果,但是一旦用户尝试刷新第一个打开的选项卡,他就会从第二个选项卡中获得结果,因为这是当前存储在会话中的内容,因为浏览器将有一个两个标签的单个会话令牌。
即使你会发现一些其他方法来实现你想要的而不使用会话,我想你会遇到类似的问题,因为HTTP是无状态的,因此你必须在服务器上存储状态。
实际上有一种方法可以在不破坏大部分功能的情况下执行此操作 - 在客户端而不是服务器端存储状态。因此,您将拥有一个没有查询字符串的URL,然后让javascript查询某些API,以便在该页面上显示任何内容。然而,这将迫使您制作某种API并使用一些不完全属于您的问题范围的JavaScript。所以有可能干净利落,但这不仅仅涉及使用Django。