Python Django:使用 Javascript 在我的模板中解析 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3345076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:33:18  来源:igfitidea点击:

Django: Parse JSON in my template using Javascript

pythonjsondjangodjango-templates

提问by wenbert

I have this in my view:

我认为:

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))

How would I "handle" / convert geodatainto JSON and pass it to my template so that I can "loop" through it like an array?

我将如何“处理”/将地理数据转换为 JSON 并将其传递给我的模板,以便我可以像数组一样“循环”它?

Am I right to think that I can do it this way? If not, then please suggest on a better solution.

我认为我可以这样做是否正确?如果没有,那么请提出更好的解决方案。

Thanks!

谢谢!

UPDATE

更新

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

I think the JSON is not escaped? How do I escape special characters inside the json string? I keep getting a newline error.

我认为JSON没有转义?如何转义 json 字符串中的特殊字符?我不断收到换行错误。

For PHP, I would json_encode() to fix this. Like in this post: Pass a PHP string to a JavaScript variable (and escape newlines)BUT how do I do that in Python/Django?

对于 PHP,我会使用 json_encode() 来解决这个问题。就像在这篇文章中一样:将 PHP 字符串传递给 JavaScript 变量(并转义换行符)但是我如何在 Python/Django 中做到这一点?

采纳答案by adamk

You could use the built-in jsonmodule:

您可以使用内置json模块:

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

You can then simply embed the resulting string inside a javascript script:

然后,您可以简单地将结果字符串嵌入到 javascript 脚本中:

<script type='text/javascript'>
var geodata = {{ geodata|safe }};
</script>

回答by wenbert

Okay, I solved my problem and would like to answer my own question. I figured it would be better for the other users here.

好的,我解决了我的问题,想回答我自己的问题。我认为这对这里的其他用户会更好。

First, get the file here: http://www.JSON.org/json_parse.js

首先,在此处获取文件:http: //www.JSON.org/json_parse.js

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

I just used escapejs: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs

我刚刚使用了escapejs:http://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs

EDIT: Thanks to Ignacio Vazquez-Abrams. It was him that helped me in #python Freenode. Should have credited him when I made this post. I didn't know he was in Stackoverflow.

编辑:感谢 Ignacio Vazquez-Abrams。是他在#python Freenode 中帮助了我。当我发这篇文章时应该归功于他。我不知道他在 Stackoverflow 中。

回答by Hiroshi Ichikawa

If you don't care about old browsers such as IE7, you can simply write:

如果你不关心IE7等老浏览器,你可以简单地写:

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

without any extra libraries. See http://caniuse.com/#feat=jsonfor browser versions which support JSON.parse().

没有任何额外的库。有关支持 JSON.parse() 的浏览器版本,请参阅http://caniuse.com/#feat=json

I believe the top-voted answer by @adamk has a potential XSS issue. If the JSON contains "</script>", the browser interprets it as the end of <script>tag. So it would be better to use @wenbert 's code or mine.

我相信@adamk 的最高投票答案存在潜在的 XSS 问题。如果 JSON 包含"</script>",浏览器会将其解释为<script>标记的结尾。所以最好使用 @wenbert 的代码或我的代码。

I tried to comment on the answer directly, but I don't have enough reputation to do that :)

我试图直接对答案发表评论,但我没有足够的声誉来做到这一点:)

回答by Konstantin Alekseev

There is a long standing ticketin django about template filter which would output json in templates. The main problem is that it hard to come up with a solution that can be used in different places of html without introducing XSS. For now the following methods can be used.

django 中有一个关于模板过滤器的长期存在的票证,它会在模板中输出 json。主要的问题是很难想出一个可以在html的不同地方使用而不引入XSS的解决方案。目前可以使用以下方法。

Store json in html element data attribute:

将 json 存储在 html 元素数据属性中:

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

Or using https://github.com/fusionbox/django-argonauts

或者使用https://github.com/fusionbox/django-argonauts

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

Do not use safefilter until you 100% sure that the json doesn't contain any data from untrusted sources.

safe100% 确定 json 不包含来自不受信任来源的任何数据之前,不要使用过滤器。

UPDATE: In Django 2.1 json_scripttag was added as official way to pass json from template context to javascript.

更新:在 Django 2.1 中,json_script标签被添加为将 json 从模板上下文传递到 javascript 的官方方式。

回答by Cory

I've found that I often want both the object version (for template code) and the JSON version (for JavaScript code), and find it a bit annoying to pass both separately to the template when one should do fine.

我发现我经常需要对象版本(用于模板代码)和 JSON 版本(用于 JavaScript 代码),并且发现在应该可以正常工作时将它们分别传递给模板有点烦人。

If you do want to take the template tag approach and don't want all the bells and whistles of django argonautsthen you can use this template tagwhich has always done the trick for me. It may not be 100% safe against untrusted data but that's never been an issue for my use cases.

如果您确实想采用模板标签方法并且不想要django argonauts 的所有花里胡哨,那么您可以使用这个模板标签,它一直对我有用。对于不受信任的数据,它可能不是 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)))