2016-03-23 44 views
2

我有一個視圖,當用戶在未登錄時嘗試訪問/amos時,應該將其重定向到/accounts/login/?next=/amos/。爲了測試此操作,我使用以下測試:Django的測試客戶端返回錯誤編碼的URL

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

如果你看Django的redirect_to_login方法,它被修飾器如login_required使用,你可以看到它將正斜槓視爲一個安全字符並且不對它們進行編碼。

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

你可以在你的測試中模仿這種行爲。但是,我認爲簡單地不對字符串進行urlencode編碼是最簡單的。重要的是要測試匿名用戶是否被重定向。在Django中應該已經有了測試,以確保url被正確編碼,所以我不確定重複這一點是否有很多好處。

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

哦,很好的接收!感謝您爲我清理這個!我想我會在我的'url_with_querystring()'函數中模仿行爲(以便面向未來) –

+0

只需重複一遍,編輯:'redirect_to_login'方法就能正確地對所有內容進行編碼*除正斜線用'!'測試)。你知道這是爲什麼嗎,@Alasdair? –

+0

它不是URL編碼的客戶端 - 它是您在視圖中使用的裝飾器調用的'redirect_to_login'方法。 – Alasdair

相關問題