web-dev-qa-db-fra.com

Passer des objets de Django à Javascript DOM

J'essaie de passer un ensemble de requêtes de Django à un modèle avec javascript.

J'ai essayé différentes approches pour résoudre ce problème:

1. Approche normale - Javascript est compliqué d'essayer d'analyser l'objet à cause de la nomenclature [& gt Objet: ID & lt, & gt Objet: ID & lt, ...]

Django Voir

Django_list = list(Some_Object.objects.all())

Modèle HTML + JS

<script type="text/javascript" >
    var js_list = {{Django_list}};
</script>

2. Approche JSON - Django échoue lors de la conversion de la liste d'objets en chaîne json N'est pas sérialisable JSON

Django Voir

Django_list = list(Some_Object.objects.all())
json_list = simplejson.dumps(Django_list)

Modèle HTML + JS

<script type="text/javascript" >
    var js_list = {{json_list}};
</script>

Donc, j'ai besoin d'aide ici :)

Quelqu'un a une suggestion/solution?

Merci!

30
Mc-

Ok, j'ai trouvé la solution!

C'était principalement parce que je n'avais pas cité les résultats. Lorsque Javascript essayait d'analyser l'objet, cela n'était pas reconnu comme chaîne.

La première étape consiste donc à:

var js_list = {{Django_list}}; 

changé en:

var js_list = "{{Django_list}}";

Après cela, j’ai réalisé que Django échappait à des personnages, je devais donc les remplacer comme ceci:

 var myJSONList = (("{{json_list}}").replace(/&(l|g|quo)t;/g, function(a,b){
                return {
                    l   : '<',
                    g   : '>',
                    quo : '"'
                }[b];
            }));

 myData = JSON.parse( myJSONList );

Note: J'ai essayé d'éviter d'échapper des personnages de Django en utilisant ceci :

var js_list = "{{json_list|safe}}"; 

Mais cela ne fonctionne pas car il est confondu avec les citations.

Enfin, j'ai trouvé un moyen d'éviter la logique de conversion au format JSON avant de l'envoyer à Javascript: 

var myDjangoList = (("{{Django_list |safe}}").replace(/&(l|g|quo)t;/g, function(a,b){
            return {
                l   : '<',
                g   : '>',
                quo : '"'
            }[b];
        }));

myDjangoList = myDjangoList.replace(/u'/g, '\'')
myDjangoList = myDjangoList.replace(/'/g, '\"')

myData = JSON.parse( myDjangoList );

Je suis sûr que cela peut être amélioré, je vous le laisse;)

Merci pour vos réponses

J'espère que ça aide quelqu'un d'autre!

24
Mc-

Même question, "Mieux" (plus récent) réponse: Django Queryset à dicter pour une utilisation dans json

Réponse de vashishtha-jogi :

Une meilleure approche consiste à utiliser DjangoJSONEncoder. Il a un support pour Decimal.

import json
from Django.core.serializers.json import DjangoJSONEncoder

prices = Price.objects.filter(product=product).values_list('price','valid_from')

prices_json = json.dumps(list(prices), cls=DjangoJSONEncoder)

Très facile à utiliser. Pas de sauter à travers des cerceaux pour la conversion individuelle champs à flotter.

Mise à jour: modification de la réponse pour utiliser json intégré au lieu de simplejson.

Cette réponse est apparue si souvent dans mes recherches sur Google et a tellement de points de vue, qu’il semble être une bonne idée de la mettre à jour et d’empêcher toute autre personne de fouiller dans SO. Suppose que Django 1.5.

29
agconti

EDIT: veuillez ne pas utiliser cette méthode, voir la réponse de @ agconti.

Utilisez le filtre escapejs: https://docs.djangoproject.com/fr/1.4/ref/templates/builtins/#escapejs

Exemple de vidage d'une liste:

var foo = [{% for x in y %}'{{ x|escapejs }}',{% endfor %}]
7
boxed

Vous pouvez utiliser la combinaison des filtres safe et escapejs dans Django.

var json_string = unescape({{json_list | safe | escapejs}});
var json_data = JSON.parse(json_string);
6
lguiel

Votre problème est que, comme souvent, vos exigences sont sous-spécifiées. À quoi voulez-vous que le JSON ressemble exactement? Vous dites que vous voulez "sérialiser le jeu de requêtes", mais dans quel format? Voulez-vous tous les champs de chaque instance de modèle, une sélection ou juste la représentation Unicode? Lorsque vous aurez répondu à cette question, vous saurez comment résoudre votre problème.

Une approche, par exemple, pourrait être d’utiliser la méthode values queryset pour générer un dictionnaire de champs pour chaque instance et de le sérialiser (vous devez d’abord le convertir en liste):

data = SomeObject.objects.values('field1', 'field2', 'field3')
serialized_data = simplejson.dumps(list(data))
4
Daniel Roseman

Vous devez marquer la chaîne comme étant sûre pour vous assurer qu'elle ne sera pas échappée.

dans un de mes projets je l'utilise comme ceci:

# app/templatetag/jsonify.py
from Django import template
from Django.utils.safestring import mark_safe
import json

register = template.Library()

@register.filter
def jsonify(list):
    return mark_safe(json.dumps(list))

et dans le modèle

{% load jsonify %}
<script type="text/javascript" >
    var js_list = {{ python_list|jsonify|escapejs }};
</script>

mais vous préférerez peut-être simplement ajouter mark_safe ou utiliser | safe dans le modèle pour éviter tous les trucs &gt;

Si le problème concerne la gestion d'objets python complexes, vous devrez peut-être utiliser votre gestionnaire comme suit: JSON date-heure entre Python et JavaScript

3
christophe31

Django offre une aide intégrée pour le scénario que vous essayez de faire ici. Ca fait plutot comme ca:

Vous avez une séquence python, une liste, un dictionnaire, etc. dans votre vue, appelons-le py_object. Une solution consiste à le jsonifier avant de le transmettre au moteur de rendu.

from Django.shortcuts import render_to_response
import json  

Puis plus tard utiliser comme ça ...

render_to_response('mypage.html',{'js_object':json.dumps(py_object)})

Dans votre modèle, utilisez ensuite le filtre safe pour importer l'objet déjà jsonized de python dans javascript, comme ceci ...

data = {{ js_object|safe }}

Cela devrait résoudre votre problème j'espère.

2
nemesisfixx

Depuis Django 2.1, il existe la balise de modèle json-script . De la docs:

json_script

Génère en toute sécurité un objet Python au format JSON, encapsulé dans une balise. prêt à être utilisé avec JavaScript.

Argument: "id" HTML de la balise.

Par exemple:

{{ value|json_script:"hello-data" }} 

Si value est le dictionnaire {'hello': 'world'}, le résultat sera:

<script id="hello-data" type="application/json">
{"hello": "world"}
</script>

Les données résultantes sont accessibles en JavaScript comme ça:

var value = JSON.parse(document.getElementById('hello-data').textContent); 

Les attaques XSS sont atténuées en échappant les caractères “<”, “>” et “&”. Pour exemple, si la valeur est {'hello': 'world</script>&amp;'}, le résultat est le suivant:

<script id="hello-data" type="application/json">
    {"hello": "world\\u003C/script\\u003E\\u0026amp;"}
</script> 

Ceci est compatible avec une politique de sécurité du contenu stricte qui interdit les scripts de page exécution. Il maintient également une séparation nette entre les données passives et code exécutable.

0
LaundroMat

Réponse consolidée (mon env: Django 2.0)

Dans views.py

import json
data= []
// fil the list
context['mydata'] = json.dumps({'data':data})

Dans le modèle

  <script type="text/javascript">
      var mydataString = "{{mydata|escapejs}}";
      console.log(JSON.parse(mydataString));
  </script>
0
rogoro