Django的测试客户端返回一个编码不正确的URL

时间:2016-03-23 14:54:12

标签: python django urlencode django-testing

当用户在没有登录时尝试访问/accounts/login/?next=/amos/时,我有一个应该重定向到/amos的视图。为了对此进行测试,我使用了以下测试:

import urllib

# I actually define this function elsewhere, I placed it here for brevity's sake
def url_with_querystring(path, **kwargs):
    return path + '?' + urllib.urlencode(kwargs)

def setUp(self):
    self.client = Client()

def test_call_view_denies_anonymous(self):
    target_url = reverse('amos_index')
    redirect_url = url_with_querystring(reverse('login'), next='/amos/')
    response = self.client.get(target_url, follow=True)
    self.assertRedirects(response, redirect_url)
    response = self.client.post(target_url, follow=True)
    self.assertRedirects(response, redirect_url)

self.assertRedirects(response, redirect_url)发生错误。具体来说,它引发了这个错误:

AssertionError: Response redirected to '/accounts/login/?next=/amos/', expected '/accounts/login/?next=%2Famos%2F'

显然,错误来自/不等于%2Fresponse返回的重定向URL似乎只是一个原始字符串,而自定义函数返回正确的URL编码字符串。在这种情况下我该怎么办?我应该不对其进行网址编码,还是django.test.client的问题?

编辑:我已经在DjangoProject网站上阅读了之前提出的bug。根据我的理解,似乎这是预期的行为?也就是说,在Django的内部系统中,URL不是编码的。想从更有经验的人那里获得一些见解,谢谢!

2 个答案:

答案 0 :(得分:2)

如果你看一下像login_required这样的装饰器使用的Django的redirect_to_login方法,你可以看到它将正斜杠视为一个安全字符并且不对它们进行编码。

login_url_parts[4] = querystring.urlencode(safe='/')

您可以在测试中模仿此行为。但是,我认为最简单的方法就是不要对字符串进行urlencode。要测试的重要一点是重定向匿名用户。应该已经在Django中进行了测试以确保url被正确编码,所以我不确定重复这个有多少好处。

redirect_url = reverse('login') + '?next=/amos/'

答案 1 :(得分:0)

这对我来说很有效
self.assertRedirects(response, reverse('login') + '?next=' + urllib.parse.quote_plus('/something/'))
不要忘记import urllib