2015-08-28 84 views
0

嗨我的django國際化在我的django網站上工作。那就是如果我瀏覽「.../en/foo/bar」和「.../nb/foo/bar」,它們工作正常。但我試圖讓下拉菜單自動更改語言,但我得到csrf錯誤。CSRF錯誤django 1.8 i18n國際化

base.html文件

<form action="{% url 'set_language' %}" method="post"> 
    {% csrf_token %} 
    <input name="next" type="hidden" value="{{ redirect_to }}"/> 
    <select name="language"> 
    {% get_current_language as LANGUAGE_CODE %} 
    {% get_available_languages as LANGUAGES %} 
    {% get_language_info_list for LANGUAGES as languages %} 
     {% for language in languages %} 
     <option value="{{ language.code }}" 
     {% if language.code == LANGUAGE_CODE %}                  selected="selected"{% endif %}> 
     {{ language.name_local }} ({{ language.code }}) 
    </option> 
    {% endfor %} 
    </select> 
     <input type="submit" value="Go"/> 
</form> 

但是我有相同的HTML另一種形式,但我不知道,但{% csrf_token %} in it. I rather place @ csrf_exempt`上處理表單視圖。 我不知道在html上是否有兩個froms是導致問題的原因。

所以,id做了什麼,我創建了自己的set_language視圖,就像在django.veiws.i18n中,並將@csrf_exempt放在它上面。

@csrf_exempt 
def set_language(request): 
    """ 
    Redirect to a given url while setting the chosen language in the 
    session or cookie. The url and the language code need to be 
    specified in the request parameters. 

    Since this view changes how the user will see the rest of the site, it must 
    only be accessed as a POST request. If called as a GET request, it will 
    redirect to the page in the request (the 'next' parameter) without changing 
    any state. 
    """ 
    print 'I am in setlang' 
    next = request.POST.get('next', request.GET.get('next')) 

    if not is_safe_url(url=next, host=request.get_host()): 
     print 'not safe' 
     next = request.META.get('HTTP_REFERER') 
     if not is_safe_url(url=next, host=request.get_host()): 
      next = '/' 
    response = http.HttpResponseRedirect(next) 
    if request.method == 'POST': 
     lang_code = request.POST.get('language', None) 
     if lang_code and check_for_language(lang_code): 
      if hasattr(request, 'session'): 
       request.session[LANGUAGE_SESSION_KEY] = lang_code 
      else: 
       response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code, 
            max_age=settings.LANGUAGE_COOKIE_AGE, 
            path=settings.LANGUAGE_COOKIE_PATH, 
            domain=settings.LANGUAGE_COOKIE_DOMAIN) 
    return response 

儘管CSRF驗證錯誤已解決,但是當我更改語言並提交時,表單無效。它只停留在同一頁面上。看起來if not is_safe_url(url=next, host=request.get_host())總是如此。我不知道我現在做錯了什麼

我剛剛意識到,我的表單發送GET請求的視圖,而不是一個職位,所以request.method是GET如何以及爲什麼是這樣嗎?在這種情況下,表單數據根本沒有進入視圖,但是當我將表單的action屬性留爲空白時,它們會提交。表單提交給調用頁面的視圖。提交到一個特定的視圖不起作用,因爲請求以某種方式變成了獲取請求

+0

'{%csrf_token%}'必須在每個表單上。 – itzMEonTV

+0

確定這是您的視圖,而不是圖書館中的視圖? – e4c5

+0

@itzmeontv是啊我有'{%csrf_token%}'這兩種形式 – flexxxit

回答

0

第一個問題 - csrf錯誤,沒有簡單的解決方案(如果你想csrf工作,沒有繞過),因爲我們不能說出什麼是在這裏發生 - 也許一些cookie相關的問題。

但第二個問題很容易解決。 django中有bug。簡而言之,當用戶更改語言時,django不會翻譯url(更改URL前面的前綴或翻譯整個URL),因此用戶將被重定向到舊的,而不是帶有舊語言前綴的翻譯的URL。這將導致重定向後切換回舊語言。

該問題的解決方案已經提交給django,並將在django 1.9中提供,但您可以從github獲取該視圖的代碼,並將其放入您的當前語言切換視圖中。

Here已完全提交該修復程序,在固定視圖中使用的urlresolvers中有一個名爲translate_url的新函數。