Как включить Django 1.2 CSRF-токен в HTML-форму, сгенерированную Javascript?

Недавно я обновился до Django 1.2.3, и мои загружаемые формы теперь сломаны. Всякий раз, когда я пытаюсь загрузить, я получаю "CSRF проверка не удалась. Запрос прерван". сообщение об ошибке.

После прочтения документации Django по этому вопросу, в нем говорится, что мне нужно добавить тег шаблона {% csrf_token%} в HTML <form> в моем шаблоне. К сожалению, мой <form> создается через JavaScript (в частности, свойство "html" ExtJs на панели).

Короче говоря, как добавить тег токена CSRF в мой <form>, когда мой <form> не включен в шаблон Django?

Ответ 1

Другой вариант - адаптировать решение на основе cookie/заголовка, показанное в в документах Django с Ext - предпочтительнее, если у вас много шаблонов и вы не хотите менять ни одного.

Просто отбросьте следующий фрагмент в файле overrides.js(или где бы вы не вносили глобальные модификации):

Ext.Ajax.on('beforerequest', function (conn, options) {
   if (!(/^http:.*/.test(options.url) || /^https:.*/.test(options.url))) {
     if (typeof(options.headers) == "undefined") {
       options.headers = {'X-CSRFToken': Ext.util.Cookies.get('csrftoken')};
     } else {
       options.headers.extend({'X-CSRFToken': Ext.util.Cookies.get('csrftoken')});
     }                        
   }
}, this);

(edit: Ext уже имеет функцию чтения файлов cookie, не нужно ее дублировать)

Ответ 2

Самый простой способ - создать скрытую форму на вашей странице, используя django, которая ничего не делает. Затем используйте JavaScript для извлечения формы и, в частности, ввода токена из формы. Наконец, вставьте или скопируйте этот токен в форму, которую вы динамически генерируете.

Вот два примера того, как вы можете опубликовать токен для JavaScript.

<input id="csrf_token" value="{{ csrf_token }}"/>

<script type="text/javascript">
var CSRF_TOKEN = document.getElementById('csrf_token').value;
</script>

или

<script type="text/javascript">
var CSRF_TOKEN = "{{ csrf_token }}";
</script>

Ответ 3

Лучшим решением является генерация кода js файла из представления/шаблона.

Затем в представлении вы можете установить токен csrf в контекст, например...

from django.core.context_processors import csrf
context = RequestContext(request)
context.update(csrf(request))

Затем в шаблоне вы можете использовать {{ csrf_token }}, чтобы получить исходное значение токена csrf, а затем использовать его для создания скрытого поля в вашей форме с именем csrfmiddlewaretoken.

Ответ 4

Представляет ли ваше мнение POST ing также отвечать на GET? В этом случае код JS может сделать запрос GET рассматриваемому представлению и проанализировать вывод для извлечения маркера CSRF. Мой JS-fu слаб, и я не уверен, как лучше всего вы можете разобрать партию с клиентской стороны.

Для широко связанного примера см. этот вопрос. В этом случае пользователь пытался выполнить POST с помощью Python script и не смог по той же причине. Решение было таким же, за исключением того, что он должен был сделать это из Python script, а не из JavaScript.

Ответ 5

Это может быть не идеальным, но это было самым быстрым решением для меня. В моем основном шаблоне в нижней части "тела" я добавил функцию javascript в свою библиотеку.

<script type="text/javascript">
    MyToolkit.Utils.getCSRFToken = function () {
         return "{% csrf_token %}";
    };
</script>

Ответ 6

При этом будет использоваться токен csrf или автоматически сгенерировать новый. Он будет обрабатывать все формы на странице. Если у вас есть внешние формы, вам нужно убедиться, что они не запускают этот код.

<script>
$(document).on('submit', 'form[method=post]', function(){
  if(!document.cookie.match('csrftoken=([a-zA-Z0-9]{32})')) {
    for(var c = ''; c.length < 32;) c += 'abcdefghijklmnopqrstuvwxyz'.charAt(Math.random() * 26)
    document.cookie = 'csrftoken=' + c + '; path=/'
  }
  if(!this.csrfmiddlewaretoken) $(this).append('<input type="hidden" name="csrfmiddlewaretoken">')
  $(this.csrfmiddlewaretoken).val(document.cookie.match('csrftoken=([a-zA-Z0-9]{32})')[1])
})
</script>

требуется jQuery 1.7 +