2010-07-27 109 views
21

我有這個在我看來,我的模板:Django的:解析JSON在使用Javascript

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並將它傳遞給我的模板,以便我能「循環「通過它像一個數組?

我是否認爲我可以這樣做?如果沒有,那麼請提出更好的解決方案。

謝謝!

UPDATE

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中做到這一點?

回答

52

你可以使用內置的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> 
+0

我得到一個錯誤,該行後: VAR地理數據=「[[" ML奎鬆街< BR/>曼達韋市,菲律賓",[10.351381999999999,123.923535],[" Talamban < BR/>菲律賓宿務市",[10.353527,123.91352500000001]]]「; 我認爲JSON不會逃脫?我如何轉義JSON字符串內的特殊字符? – wenbert 2010-07-27 16:24:34

+0

難道是你添加到你的模板var geodata =「{{geodata}}」;'?它應該沒有引號。 – adamk 2010-07-27 17:51:05

+0

不是。我已經試過了,沒有引號。我得到一個 「未捕獲的SyntaxError:意外令牌」 在谷歌和這個錯誤: 「VAR地理= [[" ML ..; [10.353527,123.91352500000001]]]; \ n」 在Firefox – wenbert 2010-07-27 23:26:52

27

好吧,我解決我的問題,並希望回答我自己的問題。我想這對其他用戶來說會更好。

首先,在這裏得到的文件: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中。

+3

哦,你那時候。 – 2010-07-28 02:03:21

+0

認真感謝;)我不知道你在#1 – wenbert 2010-07-28 10:29:19

+0

如何使用'VAR地理數據=的eval(此不同的 「{{地理| escapejs}}」);'? – simon 2011-03-30 07:41:54

9

如果你不關心舊的瀏覽器如IE7,你可以簡單的寫:

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

沒有任何額外的庫。有關支持JSON.parse()的瀏覽器版本,請參閱http://caniuse.com/#feat=json

我相信@adamk最高票數的答案有潛在的XSS問題。如果JSON包含"</script>",則瀏覽器將其解釋爲<script>標記的結尾。所以最好使用@wenbert的代碼或我的代碼。

我想直接的答案發表評論,但我沒有足夠的信譽來做到這一點:)

1

有一個長期ticket在Django大約模板過濾器會在模板輸出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> 

不要使用safe過濾器,直到你100%確保JSON不包含任何不可信數據源。

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