2010-07-27 7 views
21

je ce à mon avis:Django: Parse JSON dans mon modèle en utilisant 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)) 

Comment puis-je « gérer »/convertir géodonnées en JSON et le transmettre à mon modèle afin que je puisse " boucle "à travers elle comme un tableau? Est-ce que j'ai raison de penser que je peux le faire de cette façon? Si non, alors s'il vous plaît suggérer une meilleure solution.

Merci!

MISE À JOUR

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

Je pense que le JSON est pas échappé? Comment puis-je échapper des caractères spéciaux dans la chaîne json? Je continue à recevoir une erreur de retour à la ligne.

Pour PHP, je voudrais json_encode() pour résoudre ce problème. Comme dans ce post: Pass a PHP string to a JavaScript variable (and escape newlines) MAIS comment je fais ça en Python/Django?

Répondre

52

Vous pouvez utiliser le module json intégré:

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

Vous pouvez alors simplement intégrer la chaîne résultante à l'intérieur d'un script javascript:

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

je reçois une erreur après cette ligne: var géodonnées = « [[" ML Quezon Rue < br/> Mandaue City, Philippines ", [10,351381999999999, 123,923535]], [" Talamban < br/> La ville de Cebu, Philippines ", [10.353527, 123.91352500000001]]] "; Je pense que le JSON n'est pas échappé? Comment puis-je échapper des caractères spéciaux dans la chaîne json? – wenbert

+0

Se pourrait-il que vous ayez ajouté à votre modèle 'var geodata =" {{geodata}} ";'? Cela devrait être sans les citations. – adamk

+0

Non. J'ai essayé cela sans les citations. Je reçois un "Untaxed SyntaxError: Jeton inattendu &" dans Google et cette erreur: "var geodata = [[" ML .. ;, [10.353527, 123.91352500000001]]]; \ n" dans Firefox – wenbert

27

D'accord, je résolu mon problème et que vous souhaitez pour répondre à ma propre question. Je pensais que ce serait mieux pour les autres utilisateurs ici.

Tout d'abord, obtenir le fichier ici: http://www.JSON.org/json_parse.js

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

Je viens d'utiliser escapejs: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#escapejs

EDIT: Merci à Ignacio Vazquez-Abrams. C'est lui qui m'a aidé dans #python Freenode. J'aurais dû le créditer quand j'ai fait ce post. Je ne savais pas qu'il était dans Stackoverflow.

+3

Oh, vous l'avez fait alors. –

+0

Sérieusement merci;) Je ne savais pas que vous étiez dans Stackoverflow – wenbert

+0

en quoi est-ce différent d'utiliser 'var geodata = eval (" {{geodata | escapejs}} ");'? – simon

9

Si vous ne se soucient pas de vieux navigateurs tels que IE7, vous pouvez simplement écrire:

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

sans bibliothèques supplémentaires. Voir http://caniuse.com/#feat=json pour les versions de navigateur qui supportent JSON.parse().

Je crois que la réponse la mieux votée par @adamk a un problème XSS potentiel. Si le JSON contient "</script>", le navigateur l'interprète comme la fin de la balise <script>. Il vaudrait donc mieux utiliser le code de @wenbert ou le mien.

J'ai essayé de commenter directement la réponse, mais je n'ai pas assez réputation de le faire :)

1

Il y a une longue date ticket dans django au sujet filtre modèle qui serait JSON de sortie dans les modèles. Le principal problème est qu'il est difficile de trouver une solution qui peut être utilisée dans différents endroits de HTML sans introduire XSS. Pour l'instant, les méthodes suivantes peuvent être utilisées.

JSON de magasin dans l'attribut de données d'élément html:

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

Ou en utilisant https://github.com/fusionbox/django-argonauts

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

Ne pas utiliser safe filtre jusqu'à ce que vous 100% sûr que le JSON ne contient pas de données de untrusted sources.

1

J'ai trouvé que je voulais souvent la version de l'objet (pour le code modèle) et la version JSON (pour le code JavaScript), et je trouve ça un peu ennuyeux de passer séparément au template.

Si vous ne voulez pas prendre l'approche de l'étiquette de modèle et ne voulez pas toutes les cloches et les sifflets de django argonauts alors vous pouvez utiliser this template tag qui a toujours fait l'affaire pour moi. Il peut ne pas être sûr à 100% contre les données non fiables, mais cela n'a jamais été un problème pour mes cas d'utilisation.

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