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!
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!
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
.
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 %}]
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))
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 >
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
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.
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>&'}
, 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.
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>