2010-07-27 6 views
21

Ich habe dies aus meiner Sicht:Django: JSON in meiner Vorlage Parse Javascript mit

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

Wie würde ich "Griff"/convert Geodaten in JSON und es zu meiner Vorlage übergeben, so dass ich kann " Schleife "durch sie wie ein Array?

Habe ich Recht zu denken, dass ich es so machen kann? Wenn nicht, dann schlagen Sie bitte eine bessere Lösung vor.

Danke!

UPDATE

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

ich glaube, die JSON nicht entgangen ist? Wie entkomme ich Sonderzeichen innerhalb der JSON-Zeichenfolge? Ich bekomme immer einen Newline-Fehler.

Für PHP würde ich json_encode(), um dies zu beheben. Wie in diesem Beitrag: Pass a PHP string to a JavaScript variable (and escape newlines) ABER wie mache ich das in Python/Django?

Antwort

52

Sie könnten das eingebaute in json Modul:

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

Sie können dann einfach die resultierende Zeichenfolge in einem JavaScript-Skript einbetten:

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

Ich erhalte eine Fehlermeldung nach dieser Zeile: var Geodaten = „[[" ML Quezon Straße < br/> Mandaue City, Philippinen ", [10,351381999999999, 123,923535]], [" Talamban < br/> Cebu City, Philippinen ", [10,353527, 123,91352500000001]]] "; Ich denke, die JSON ist nicht maskiert? Wie entkomme ich Sonderzeichen innerhalb der JSON-Zeichenfolge? – wenbert

+0

Könnte es sein, dass Sie Ihre Vorlage 'var geodata =" {{geodata}} "hinzugefügt haben; Es sollte ohne die Anführungszeichen sein. – adamk

+0

Nein. Ich habe das ohne die Zitate versucht. Ich bekomme einen "Uncaught SyntaxError: Unexpected token &" in Google und diesen Fehler: "var geodata = [[" ML ..;, [10.353527, 123.91352500000001]]]; \ n" in Firefox – wenbert

27

Okay, ich mein Problem gelöst und möchte um meine eigene Frage zu beantworten. Ich dachte, es wäre besser für die anderen Benutzer hier.

Zunächst holen Sie die Datei hier: http://www.JSON.org/json_parse.js

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

I verwendet escapejs gerade: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs

EDIT: Dank Ignacio Vazquez-Abrams. Er hat mir in #python Freenode geholfen. Sollte ihm gutgeschrieben haben, als ich diesen Posten gemacht habe. Ich wusste nicht, dass er in Stackoverflow war.

+3

Oh, hast du dann? –

+0

Ernsthaft danke;) Ich wusste nicht, dass Sie in Stackoverflow waren – wenbert

+0

Wie unterscheidet sich das von 'var geodata = eval (" {{Geodaten | escapejs}} ");'? – simon

9

Wenn Sie nicht über alten Browser wie IE7 egal, können Sie einfach schreiben:

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

ohne zusätzliche Bibliotheken. Unter http://caniuse.com/#feat=json finden Sie Browserversionen, die JSON.parse() unterstützen.

Ich glaube, dass die von @adamk am häufigsten gewählte Antwort ein potenzielles XSS-Problem hat. Wenn der JSON "</script>" enthält, interpretiert der Browser ihn als das Ende des Tags <script>. Es wäre also besser, @wenbert oder meinen Code zu verwenden.

Ich habe versucht, direkt auf der Antwort zu kommentieren, aber ich habe das :) nicht genug Ruf zu tun

1

Es gibt ein ticket in django über Template-Filter seit langem ist die ausgeben würde json in Vorlagen. Das Hauptproblem ist, dass es schwierig ist, eine Lösung zu finden, die an verschiedenen Stellen von HTML verwendet werden kann, ohne XSS einzuführen. Für jetzt können die folgenden Methoden verwendet werden.

Shop json in html-Element Datenattribut:

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

Oder mit https://github.com/fusionbox/django-argonauts

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

nicht safe Filter Verwenden Sie, bis Sie 100% sicher, dass die json keine Daten aus nicht vertrauenswürdigen enthält Quellen.

1

Ich habe festgestellt, dass ich oft sowohl die Objektversion (für Vorlagencode) als auch die JSON-Version (für JavaScript-Code) möchte, und es ein wenig nervig finde, beide separat an die Vorlage zu übergeben, wenn man es gut machen sollte.

Wenn Sie möchten, die Vorlage Tag Ansatz und nicht alle Schnickschnack von django argonauts, dann können Sie this template tag, die immer den Trick für mich getan hat. Es ist möglicherweise nicht 100% sicher gegen nicht vertrauenswürdige Daten, aber das war nie ein Problem für meine Anwendungsfälle.

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