CSRF错误django 1.8 i18n国际化

时间:2015-08-28 08:58:33

标签: html django django-csrf django-i18n

您好我的django国际化正在我的django网站上工作。那就是我浏览" ... / en / foo / bar"和" ... / nb / foo / bar"他们工作得很好。但我试图让一个下拉菜单自动更改语言,但我得到csrf错误。

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上是否有两个来源是导致问题的原因。

所以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属性留空时它们会提交。表单提交到调用页面的视图。提交到特定视图不起作用,因为请求以某种方式成为获取请求

1 个答案:

答案 0 :(得分:0)

第一个问题--csrf错误,没有简单的解决方案(如果你想让csrf工作,而不是绕过),因为我们无法分辨这里发生了什么 - 可能是一些与cookie有关的问题。

但第二个问题很容易解决。 django中有bug。简单来说,当用户更改语言时,django将不会翻译url(在URL前面更改前缀或翻译整个URL),因此用户将被重定向到旧的,而不是使用旧语言前缀翻译的URL。这将导致重定向后切换回旧语言。

该问题的解决方案已经提交给django,并且可以在django 1.9中使用,但是您可以从github获取该视图的代码并将其替换为当前的语言切换视图。

Here是针对该修复的完全提交,在固定视图中使用urlresolvers中有一个名为translate_url的新函数。