【问题标题】:Django: Parse JSON in my template using JavascriptDjango:使用 Javascript 在我的模板中解析 JSON
【发布时间】:2011-03-21 16:18:15
【问题描述】:

我认为这是:

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

我将如何“处理”/将 geodata 转换为 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() 来解决这个问题。就像在这篇文章中一样:Pass a PHP string to a JavaScript variable (and escape newlines) 但是我如何在 Python/Django 中做到这一点?

【问题讨论】:

    标签: python json django django-templates


    【解决方案1】:

    我发现我经常需要对象版本(用于模板代码)和 JSON 版本(用于 JavaScript 代码),并且发现将两者分别传递给模板有点烦人,而当一个人应该做得很好时。

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

    【讨论】:

      【解决方案2】:

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

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

      在您 100% 确定 json 不包含来自不受信任来源的任何数据之前,请勿使用 safe 过滤器。

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

      【讨论】:

        【解决方案3】:

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

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

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

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

        我试图直接评论答案,但我没有足够的声誉来这样做:)

        【讨论】:

          【解决方案4】:

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

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

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

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

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

          【讨论】:

          • 这与使用var geodata = eval("{{geodata|escapejs}}"); 有何不同?
          • 这与var geodata = {{ geodata|escapejs }}(不在字符串中)有何不同?
          • json_parse.js 的链接现在是 404s,但同样的方法适用于 JSON.parse();,记录在这里:developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
          【解决方案5】:

          您可以使用内置的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>
          

          【讨论】:

          • 我在这行之后得到一个错误:var geodata = "[["ML Quezon Street<br/>Mandaue City, Philippines", [10.351381999999999, 123.923535]], ["Talamban< br/>菲律宾宿务市”, [10.353527, 123.91352500000001]]]";我认为 JSON 没有转义?如何转义 json 字符串中的特殊字符?
          • 会不会是您在模板中添加了var geodata = "{{ geodata }}";?它应该没有引号。
          • 不。我试过没有引号。我在 Google 中收到“Uncaught SyntaxError: Unexpected token &”这个错误:“var geodata = [["M. L...;, [10.353527, 123.91352500000001]]];\n”在 Firefox 中
          • 您必须启用自动转义...尝试放入您的模板{{ geodata|safe }}(也已在答案中修复)
          • 我相信这段代码存在潜在的 XSS 问题。如果 JSON 包含“”,浏览器会将其解释为
          猜你喜欢
          • 2018-09-30
          • 2021-09-29
          • 2019-04-23
          • 2019-02-05
          • 2020-07-02
          • 2023-03-11
          • 2016-11-13
          • 2010-12-11
          相关资源
          最近更新 更多