Ошибка CSRF django 1.8 интернационализация 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 как и почему это так? В этом случае данные формы вообще не попадают в представление, но они отправляются, когда я оставляю атрибут действия формы пустым. Форма подчиняется представлению, вызвавшему страницу. Отправка в определенное представление не работает, так как запрос каким-то образом становится запросом на получение


person flexxxit    schedule 28.08.2015    source источник
comment
{% csrf_token %} должен быть в каждой форме.   -  person itzMEonTV    schedule 28.08.2015
comment
Уверены, что вызывается именно ваш вид, а не тот, что из библиотеки?   -  person e4c5    schedule 28.08.2015
comment
@itzmeontv да, у меня есть {% csrf_token %} в обеих формах   -  person flexxxit    schedule 28.08.2015
comment
@ e4c5 Да, я знаю это, потому что код для вывода данных в представлении находится в моих print 'I am in setlang и print 'not safe. «небезопасно» всегда печатается, когда я отправляю форму, а следующий также всегда пуст (нет)   -  person flexxxit    schedule 28.08.2015


Ответы (1)


С первой проблемой - ошибкой csrf, простого решения нет (если вы хотите, чтобы csrf работал, а не обходился), потому что мы не можем сказать, что здесь происходит - может быть, какая-то проблема, связанная с файлами cookie.

Но вторая проблема решается просто. В django есть ошибка. Проще говоря, django не будет переводить URL-адрес (менять префикс перед URL-адресом или переводить весь URL-адрес), когда пользователь меняет язык, поэтому пользователь будет перенаправлен на старый, не переведенный URL-адрес со старым языковым префиксом. Это приведет к переключению на старый язык после перенаправления.

Решение этой проблемы уже отправлено в django и будет доступно в django 1.9, но вы можете получить код этого представления с github и поместить его вместо текущего представления переключения языка.

Здесь полный коммит для этого исправления, есть новая функция translate_url в urlresolvers, которая используется в фиксированном виде.

person GwynBleidD    schedule 28.08.2015