Django: Разбор JSON в моем шаблоне с использованием Javascript - PullRequest
25 голосов
/ 27 июля 2010

У меня есть это на мой взгляд:

string_location = myaddress2
    geodata = []
    for place, (lat, lng) in g.geocode(string_location,exactly_one=False):
        geodata.append((place, (lat, lng)))

    geodata_results = len(geodata)

    data = {"geodata": geodata, "geodata_results":geodata_results }
    return render_to_response("business/business_view.html",
                              data, context_instance=RequestContext(request))

Как бы я "обработал" / конвертировал геоданные в JSON и передал его в свой шаблон, чтобы я мог "перебрать"это как массив?

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

Спасибо!

ОБНОВЛЕНИЕ

var geodata = "[["M. L. Quezon Street<br/>Mandaue City, Philippines", [10.351381999999999, 123.923535]], ["Talamban<br/>Cebu City, Philippines", [10.353527, 123.91352500000001]]]"; 

Я думаю, что JSON не сбежал?Как я могу избежать специальных символов внутри строки JSON?Я продолжаю получать сообщение об ошибке новой строки.

Для PHP я бы исправил json_encode ().Как в этом посте: Передать строку PHP в переменную JavaScript (и экранировать символы новой строки) НО, как мне это сделать в Python / Django?

Ответы [ 5 ]

62 голосов
/ 27 июля 2010

Вы можете использовать встроенный модуль json:

>>> import json
>>> geodata = [ ( "Here", (1003,3004) ), ("There", (1.2,1.3)) ]
>>> json.dumps(geodata)
'[["Here", [1003, 3004]], ["There", [1.2, 1.3]]]'

Затем вы можете просто вставить полученную строку в скрипт javascript:

<script type='text/javascript'>
var geodata = {{ geodata|safe }};
</script>
27 голосов
/ 28 июля 2010

Хорошо, я решил свою проблему и хотел бы ответить на свой вопрос.Я подумал, что для других пользователей было бы лучше.

Во-первых, получите файл здесь: http://www.JSON.org/json_parse.js

var geodata = json_parse("{{geodata|escapejs}}");

Я просто использовал escapejs: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs

РЕДАКТИРОВАТЬ: Благодаря Игнасио Васкес-Абрамс.Именно он помог мне в #python Freenode.Должен был зачислить его, когда я сделал этот пост.Я не знал, что он был в Stackoverflow.

12 голосов
/ 13 ноября 2015

Если вам не нужны старые браузеры, такие как IE7, вы можете просто написать:

var geodata = JSON.parse("{{geodata|escapejs}}");

без каких-либо дополнительных библиотек.См. http://caniuse.com/#feat=json для версий браузера, которые поддерживают JSON.parse ().

Я полагаю, что ответ @adamk с наибольшим количеством голосов имеет потенциальную проблему XSS.Если JSON содержит "</script>", браузер интерпретирует его как конец тега <script>.Поэтому было бы лучше использовать код @wenbert или мой.

Я пытался прокомментировать ответ напрямую, но у меня недостаточно репутации, чтобы сделать это:)

2 голосов
/ 28 апреля 2017

Я обнаружил, что мне часто нужны и версия объекта (для кода шаблона), и версия JSON (для кода JavaScript), и нахожу немного раздражающим передавать оба шаблона в отдельности, когда все будет хорошо.

Если вы хотите использовать подход с тегами шаблонов и не хотите, чтобы все колокола и свистки аргонавтов Джанго , вы можете использовать этот шаблонный тег , который имеетвсегда делал свое дело для меня.Это может быть не на 100% безопасно от ненадежных данных, но это никогда не было проблемой для моих случаев использования.

"""
Usage:

{% import json_tags %}

var = myJsObject = {{ template_var|to_json }};

Features:

- Built in support for dates, datetimes, lazy translations.
- Safe escaping of script tags.
- Support for including QueryDict objects.
- Support for custom serialization methods on objects via defining a `to_json()` method.
"""

import datetime
import json
from decimal import Decimal
from django import template
from django.http import QueryDict
from django.utils.encoding import force_str
from django.utils.functional import Promise
from django.utils.safestring import mark_safe

register = template.Library()

ISO_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'


def json_handler(obj):
    if callable(getattr(obj, 'to_json', None)):
        return obj.to_json()
    elif isinstance(obj, datetime.datetime):
        return obj.strftime(ISO_DATETIME_FORMAT)
    elif isinstance(obj, datetime.date):
        return obj.isoformat()
    elif isinstance(obj, datetime.time):
        return obj.strftime('%H:%M:%S')
    elif isinstance(obj, Decimal):
        return float(obj)  # warning, potential loss of precision
    elif isinstance(obj, Promise):
        return force_str(obj)  # to support ugettext_lazy
    else:
        return json.JSONEncoder().default(obj)


@register.filter
def to_json(obj):
    def escape_script_tags(unsafe_str):
        # seriously: http://stackoverflow.com/a/1068548/8207
        return unsafe_str.replace('</script>', '<" + "/script>')

    # json.dumps does not properly convert QueryDict array parameter to json
    if isinstance(obj, QueryDict):
        obj = dict(obj)
    return mark_safe(escape_script_tags(json.dumps(obj, default=json_handler)))
1 голос
/ 21 декабря 2016

В django существует давний тикет о фильтре шаблонов, который выводил бы json в шаблонах. Основная проблема заключается в том, что сложно придумать решение, которое можно использовать в разных местах html без введения XSS. На данный момент можно использовать следующие методы.

Сохранить json в атрибуте данных html-элемента:

<div data-geodata="{{json_dump_of_geodata}}"></div>
<script>
  var geodata = JSON.parse(
      document.querySelectorAll('[data-geodata]')[0].getAttribute('data-geodata')
  );
</script>

Или используя https://github.com/fusionbox/django-argonauts

<script>
    var geodata = {{geodata|json}};
</script>

Не используйте фильтр safe, пока вы не убедитесь на 100%, что json не содержит данных из ненадежных источников.

ОБНОВЛЕНИЕ: В Django 2.1 тег json_script был добавлен в качестве официального способа передачи json из контекста шаблона в javascript.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...