2010-07-27 14 views
21

ho questo a mio avviso:Django: Parse JSON nel mio modello utilizzando 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)) 

Come faccio a "gestire"/convertire geodati in JSON e passarlo al mio modello in modo che posso " loop "attraverso di esso come un array?

Ho ragione di pensare che posso farlo in questo modo? In caso contrario, si prega di suggerire su una soluzione migliore.

Grazie!

UPDATE

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

penso che il JSON non è sfuggito? Come faccio a sfuggire a caratteri speciali all'interno della stringa json? Continuo a ricevere un errore di nuova riga.

Per PHP, vorrei json_encode() per risolvere questo problema. Come in questo post: Pass a PHP string to a JavaScript variable (and escape newlines) MA come faccio a farlo in Python/Django?

risposta

52

È possibile utilizzare il built-in json modulo:

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

È quindi possibile semplicemente inserire la stringa risultante all'interno di uno script javascript:

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

ottengo un errore dopo questa riga: var geodati = "[[" ML Quezon Via < br/> Mandaue City, Filippine ", [10,351381999999999, 123,923,535 mila]], [" Talamban < br/> Cebu City, Philippines ", [10.353527, 123.91352500000001]]] "; Penso che il JSON non sia sfuggito? Come faccio a sfuggire a caratteri speciali all'interno della stringa json? – wenbert

+0

Potrebbe essere che hai aggiunto al tuo template 'var geodata =" {{geodata}} ";'? Dovrebbe essere senza le virgolette. – adamk

+0

No. L'ho provato senza le virgolette. Ottiene "Uncaught SyntaxError: Token inaspettato &" in Google e questo errore: "var geodata = [[" ML ..;, [10.353527, 123.91352500000001]]]; \ n" in Firefox – wenbert

27

Va bene, ho risolto il mio problema e desideri per rispondere alla mia stessa domanda. Ho pensato che sarebbe stato meglio per gli altri utenti qui.

primo luogo, ottenere il file qui: escapejs http://www.JSON.org/json_parse.js

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

ho appena usato: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs

EDIT: Grazie a Ignacio Vazquez-Abrams. È stato lui a darmi una mano in #python Freenode. Dovrei averlo accreditato quando ho fatto questo post. Non sapevo che fosse in Stackoverflow.

+3

Oh, allora. –

+0

Seriamente grazie;) Non sapevo che fossi in StackOverflow – wenbert

+0

come è diverso dall'uso di 'var geodata = eval (" {{geodata | escapejs}} ");'? – simon

9

Se non si cura di vecchi browser come IE7, si può semplicemente scrivere:

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

senza librerie extra. Vedi http://caniuse.com/#feat=json per le versioni del browser che supportano JSON.parse().

Credo che la risposta più votata da @adamk abbia un potenziale problema XSS. Se il JSON contiene "</script>", il browser lo interpreta come la fine del tag <script>. Quindi sarebbe meglio usare il codice di @wenbert o il mio.

ho cercato di commentare la risposta direttamente, ma io non ho abbastanza reputazione per farlo :)

1

C'è una lunga standing ticket in Django su filtro modello che sarebbe uscita JSON nei template. Il problema principale è che è difficile trovare una soluzione che possa essere utilizzata in diverse posizioni di html senza introdurre XSS. Per ora è possibile utilizzare i seguenti metodi.

Conservare JSON in attributo dato html:

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

o utilizzando https://github.com/fusionbox/django-argonauts

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

Non utilizzare safe filtro fino a quando non sicuro al 100% che il JSON non contiene alcun dato da non attendibile fonti.

1

Ho riscontrato che spesso desidero sia la versione dell'oggetto (per il codice modello) che la versione JSON (per codice JavaScript) e trovo un po 'noioso passare entrambi separatamente al modello quando si dovrebbe fare bene.

Se si desidera adottare l'approccio di tag di modello e non si desidera tutte le campane e fischietti di django argonauts, è possibile utilizzare this template tag che ha sempre fatto il trucco per me. Potrebbe non essere sicuro al 100% contro i dati non attendibili, ma non è mai stato un problema per i miei casi d'uso.

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