it-swarm.com.ru

Передача объектов из Django в Javascript DOM

Я пытаюсь передать Query Set из Django в шаблон с JavaScript.

Я пробовал разные подходы, чтобы решить эту проблему:

1. Нормальный подход - Javascript запутывается при попытке разобрать объект из-за номенклатуры [& gt Object: ID & lt, & gt Object: ID & lt, ...]

Джанго Вью

Django_list = list(Some_Object.objects.all())

Шаблон HTML + JS

<script type="text/javascript" >
    var js_list = {{Django_list}};
</script>

2. Подход JSON - Django не может преобразовать список объектов в строку json Не сериализуем в JSON

Джанго Вью

Django_list = list(Some_Object.objects.all())
json_list = simplejson.dumps(Django_list)

Шаблон HTML + JS

<script type="text/javascript" >
    var js_list = {{json_list}};
</script>

Итак, мне нужна помощь здесь :)

У кого-нибудь есть предложение/решение?

Спасибо!

30
Mc-

Хорошо, я нашел решение!

Главным образом это было из-за не процитирования результатов. Когда Javascript пытался разобрать объект, он не был распознан как строка.

Итак, первый шаг:

var js_list = {{Django_list}}; 

изменился на:

var js_list = "{{Django_list}}";

После этого я понял, что Django избегает символов, поэтому мне пришлось заменить их следующим образом:

 var myJSONList = (("{{json_list}}").replace(/&(l|g|quo)t;/g, function(a,b){
                return {
                    l   : '<',
                    g   : '>',
                    quo : '"'
                }[b];
            }));

 myData = JSON.parse( myJSONList );

Примечание: я пытался избежать экранирования символов из Django, используя это :

var js_list = "{{json_list|safe}}"; 

Но это не работает, потому что его путают с кавычками.

Наконец, я нашел способ избежать логики конвертации в JSON на серверной стороне перед отправкой в ​​Javascript: 

var myDjangoList = (("{{Django_list |safe}}").replace(/&(l|g|quo)t;/g, function(a,b){
            return {
                l   : '<',
                g   : '>',
                quo : '"'
            }[b];
        }));

myDjangoList = myDjangoList.replace(/u'/g, '\'')
myDjangoList = myDjangoList.replace(/'/g, '\"')

myData = JSON.parse( myDjangoList );

Я уверен, что это может быть улучшено, я дам это вам;)

Спасибо за ваши ответы

Надеюсь, это поможет кому-то еще!

24
Mc-

Тот же вопрос, «Лучше» (более недавний) ответ: Django Queryset для использования в json

Ответить vashishtha-jogi :

Лучше всего использовать DjangoJSONEncoder. Он имеет поддержку для десятичной.

import json
from Django.core.serializers.json import DjangoJSONEncoder

prices = Price.objects.filter(product=product).values_list('price','valid_from')

prices_json = json.dumps(list(prices), cls=DjangoJSONEncoder)

Очень прост в использовании. Нет прыжков через обручи для преобразования личности поля для плавания.

Обновление: изменен ответ на использование встроенного json вместо simplejson.

Этот ответ возникал так часто в моих поисках в Google и имеет так много просмотров, что кажется хорошей идеей обновить его и спасти кого-нибудь еще от копания в SO. Предполагается Django 1.5.

29
agconti

Правка: пожалуйста, не используйте этот метод, см. Ответ @ agconti.

Используйте фильтр escapejs: https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#escapejs

Пример сброса списка:

var foo = [{% for x in y %}'{{ x|escapejs }}',{% endfor %}]
7
boxed

Наборы запросов Django are, сериализуемые JSON . Некоторые типы полей (например, дата, по-видимому) не могут быть сериализованы в is. Обходной путь для объектов даты размещен в еще один вопрос по JSON и Python .

Я бы порекомендовал создавать словари непосредственно в самом JavaScript. Данные модели как это:

class Article(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField()
    content = models.TextField()

class Author(models.Model):
    article = models.ForeignKey("Article", related_name="authors")
    first_name=models.CharField(max_length=100)
    last_name=models.CharField(max_length=100)

Я бы сделал что-то подобное в шаблоне:

<script type="text/javascript">
    var articles = [
    {% for article in article_list %}
        {% if not forloop.first %},{% endif %}
        {
            title: "{{ article.title }}",
            slug: "{{ article.slug }}",
            content: "{{ article.content }}",
            authors: [
            {% for author in article.authors.all %}
                {% if not forloop.first %},{% endif %}
                {
                    first_name: "{{ author.first_name }}",
                    last_name: "{{ author.last_name }}",
                }
            {% endfor %}
            ]
        }
    {% endfor %}
    ]
</script>

Если вы, возможно, сформулировали вопрос немного плохо и не планируете вставить код в тег <script> и на самом деле по какой-то причине need JSON, я просто сделал бы цикл в представлении и создайте список dicts, с которым у JSON нет проблем с сериализацией, а у JavaScript нет проблем с пониманием.

7
Jordan Reiter

Вы можете использовать комбинацию safe и escapejs встроенного фильтра в Django.

var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);
6
lguiel

Ваша проблема в том, что, как это часто бывает, ваши требования недостаточно конкретизированы. Как именно вы хотите, чтобы JSON выглядел? Вы говорите, что хотите «сериализовать набор запросов», но в каком формате? Вам нужны все поля из каждого экземпляра модели, выбора или просто представления в юникоде? Когда вы ответите на этот вопрос, вы узнаете, как решить свою проблему.

Например, одним из подходов может быть использование метода набора запросов values для вывода словаря полей для каждого экземпляра и его сериализации (сначала необходимо преобразовать его в список):

data = SomeObject.objects.values('field1', 'field2', 'field3')
serialized_data = simplejson.dumps(list(data))
4
Daniel Roseman

Вы должны пометить строку как безопасную, чтобы быть уверенным, что она не экранирована.

в одном из моих проектов я использую это так:

# app/templatetag/jsonify.py
from Django import template
from Django.utils.safestring import mark_safe
import json

register = template.Library()

@register.filter
def jsonify(list):
    return mark_safe(json.dumps(list))

и в шаблоне

{% load jsonify %}
<script type="text/javascript" >
    var js_list = {{ python_list|jsonify|escapejs }};
</script>

но вы можете предпочесть просто добавить mark_safe или использовать | safe в шаблоне, чтобы избежать всего, что связано с &gt;

Если проблема заключается в обработке сложного объекта Python, вам, возможно, придется сделать свой обработчик следующим образом: JSON datetime между Python и JavaScript

3
christophe31

Django предлагает встроенную помощь по самому сценарию, который вы пытаетесь сделать здесь. Это выглядит примерно так:

У вас есть последовательность Python, список, словарь и т.д., Давайте назовем это py_object. Один из подходов заключается в том, чтобы jsonify, прежде чем передавать его в механизм рендеринга.

from Django.shortcuts import render_to_response
import json  

Затем позже использовать, как это ...

render_to_response('mypage.html',{'js_object':json.dumps(py_object)})

В вашем шаблоне затем используйте фильтр safe для импорта уже jsonized объекта из python в javascript, как это ...

data = {{ js_object|safe }}

Это должно решить вашу проблему, я надеюсь.

2
nemesisfixx

Начиная с Django 2.1, существует тег шаблона json-script . Из документов:

json_script

Безопасно выводит объект Python в виде JSON, завернутый в тег, готов к использованию с JavaScript.

Аргумент: HTML-идентификатор тега.

Например:

{{ value|json_script:"hello-data" }} 

Если значением является словарь {'hello': 'world'}, вывод будет:

<script id="hello-data" type="application/json">
{"hello": "world"}
</script>

Полученные данные могут быть доступны в JavaScript как это:

var value = JSON.parse(document.getElementById('hello-data').textContent); 

Атаки XSS смягчаются путем экранирования символов «<», «>» и «&». За Например, если значение {'hello': 'world</script>&amp;'}, вывод:

<script id="hello-data" type="application/json">
    {"hello": "world\\u003C/script\\u003E\\u0026amp;"}
</script> 

Это совместимо со строгой политикой безопасности контента, которая запрещает скрипты на странице выполнение. Он также поддерживает четкое разделение между пассивными данными и исполняемый код.

0
LaundroMat

Сводный ответ (мой env: Django 2.0)

В views.py

import json
data= []
// fil the list
context['mydata'] = json.dumps({'data':data})

В шаблоне

  <script type="text/javascript">
      var mydataString = "{{mydata|escapejs}}";
      console.log(JSON.parse(mydataString));
  </script>
0
rogoro