web-dev-qa-db-fra.com

AngularJS avec Django - Balises de modèles en conflit

Je souhaite utiliser AngularJS avec Django, mais ils utilisent tous les deux {{ }} comme balises de modèle. Existe-t-il un moyen simple de changer l’un des deux pour utiliser une autre balise de modèle personnalisée?

292
Endophage

Pour Angular 1.0, utilisez l’API $ interpolateProvider pour configurer les symboles d’interpolation: http://docs.angularjs.org/api/ng.$interpolateProvider .

Quelque chose comme ça devrait faire l'affaire:

myModule.config(function($interpolateProvider) {
  $interpolateProvider.startSymbol('{[{');
  $interpolateProvider.endSymbol('}]}');
});

Gardez à l'esprit deux choses:

  • le mélange de modèles côté serveur et côté client est rarement une bonne idée et doit être utilisé avec prudence. Les principaux problèmes sont: la maintenabilité (difficile à lire) et la sécurité (une double interpolation pourrait exposer un nouveau vecteur de sécurité - par exemple, tout en évitant de créer des modèles côté serveur ou client, mais leur combinaison pourrait ne pas l'être).
  • si vous commencez à utiliser des directives tierces (composants) qui utilisent {{ }} dans leurs modèles, votre configuration les supprimera. ( correction en attente )

Bien que nous ne puissions rien faire à propos du premier problème, à part avertir les gens, nous devons nous attaquer au deuxième problème.

295
Igor Minar

vous pouvez peut-être essayer verbatim balise de modèle Django .__ et l'utiliser comme ceci:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>

{% verbatim %}
<div ng-app="">
    <p>10 is {{ 5 + 5 }}</p>
</div>
{% endverbatim %}

116
Salamonell Typhi

Si vous avez bien séparé les sections de page, vous pouvez facilement utiliser les balises angularjs dans la portée des balises "raw".

Dans jinja2

{% raw %}
    // here you can write angularjs template tags.
{% endraw %}

Dans le modèle Django (au dessus de 1.5)

{% verbatim %}    
    // here you can write angularjs template tags.
{% endverbatim %}
42
thanksnote

Nous avons créé un filtre very simple dans Django 'ng' qui facilite le mélange des deux:

foo.html:

...
<div>
  {{ Django_context_var }}
  {{ 'angularScopeVar' | ng }}
  {{ 'angularScopeFunction()' | ng }}
</div>
...

Le filtre ng ressemble à ceci:

from Django import template
from Django.utils import safestring

register = template.Library()


@register.filter(name='ng')
def Angularify(value):
  return safestring.mark_safe('{{%s}}' % value)
29
Wes Alvaro

J'ai donc eu une aide précieuse dans le canal angulaire IRC aujourd'hui. Il s'avère que vous pouvez très facilement changer les balises de template d'Angular. Les extraits nécessaires ci-dessous doivent être inclus après votre inclusion angulaire (l'exemple donné apparaît sur leurs listes de diffusion et utiliserait (()) comme nouvelle balise de modèle, remplaçant la votre)

angular.markup('(())', function(text, textNode, parentElement){
  if (parentElement[0].nodeName.toLowerCase() == 'script') return;
  text = text.replace(/\(\(/g,'{{').replace(/\)\)/g, '}}');
  textNode.text(text);
  return angular.markup('{{}}').call(this, text, textNode, parentElement);
});

angular.attrMarkup('(())', function(value, name, element){
    value = value.replace(/\(\(/g,'{{').replace(/\)\)/, '}}');
    element[0].setAttribute(name, value);
    return angular.attrMarkup('{{}}').call(this, value, name, element);
});

De plus, on m'a signalé une amélioration à venir qui exposerait les propriétés startSymbol et endSymbol pouvant être définies sur les balises de votre choix.

26
Endophage

Je vote contre l'utilisation de doubles parenthèses (()) comme balise modèle. Cela peut bien fonctionner tant qu’aucun appel de fonction n’est impliqué, mais lorsque vous essayez, procédez comme suit:

ng:disabled=(($invalidWidgets.visible()))

avec Firefox (10.0.2) sur Mac j'ai eu une erreur terriblement longue au lieu de la logique prévue. <[]> s'est bien passé pour moi, du moins jusqu'à maintenant.

Edit 2012-03-29: Veuillez noter que $ invalidWidgets est obsolète. Cependant, j'utiliserais encore un autre wrapper que les doubles accolades. Pour toute version angulaire supérieure à 0.10.7 (je suppose), vous pouvez changer l'encapsuleur beaucoup plus facilement dans la définition de votre application/module:

angular.module('YourAppName', [], function ($interpolateProvider) {
    $interpolateProvider.startSymbol('<[');
    $interpolateProvider.endSymbol(']>');
}); 

Documents API .

17
Lukas Bünger

J'ai trouvé le code ci-dessous utile. J'ai trouvé le code ici: http://djangosnippets.org/snippets/2787/

"""
filename: angularjs.py

Usage:
    {% ng Some.angular.scope.content %}

e.g.
    {% load angularjs %}
    <div ng-init="yourName = 'foobar'">
        <p>{% ng yourName %}</p>
    </div>
"""

from Django import template

register = template.Library()

class AngularJS(template.Node):
    def __init__(self, bits):
        self.ng = bits

    def render(self, ctx):
        return "{{%s}}" % " ".join(self.ng[1:])

def do_angular(parser, token):
    bits = token.split_contents()
    return AngularJS(bits)

register.tag('ng', do_angular)
15
nu everest

Vous pouvez toujours utiliser ng-bind au lieu de {{}} http://docs.angularjs.org/api/ng/directive/ngBind

<span ng-bind="name"></span>
14
Indomitable

Si vous utilisez Django 1.5 et plus récent, utilisez:

  {% verbatim %}
    {{if dying}}Still alive.{{/if}}
  {% endverbatim %}

Si vous êtes coincé avec Django 1.2 sur Appengine, étendez la syntaxe de Django avec la commande de modèle verbatim comme ceci ...

from Django import template

register = template.Library()

class VerbatimNode(template.Node):

    def __init__(self, text):
        self.text = text

    def render(self, context):
        return self.text

@register.tag
def verbatim(parser, token):
    text = []
    while 1:
        token = parser.tokens.pop(0)
        if token.contents == 'endverbatim':
            break
        if token.token_type == template.TOKEN_VAR:
            text.append('{{')
        Elif token.token_type == template.TOKEN_BLOCK:
            text.append('{%')
        text.append(token.contents)
        if token.token_type == template.TOKEN_VAR:
            text.append('}}')
        Elif token.token_type == template.TOKEN_BLOCK:
            text.append('%}')
    return VerbatimNode(''.join(text))

Dans votre fichier, utilisez:

from google.appengine.ext.webapp import template
template.register_template_library('utilities.verbatim_template_tag')

Source: http://bamboobig.blogspot.co.at/2011/09/notebook-using-jquery-templates-in.html

11
cat

Pour AngularJS v1.3.3, vous devez définir vos propres balises de modèle, comme ceci

Module AngularJS

angular.module('myapp', []).config(function($interpolateProvider) {
    $interpolateProvider.startSymbol('{$');
    $interpolateProvider.endSymbol('$}');
});

Page Web

<a>{$ variable $}</a> 
9
Alex Jolig

Vous pouvez indiquer à Django de générer {{ et }}, ainsi que d'autres chaînes de modèle réservées, en utilisant la balise {% templatetag %} .

Par exemple, utiliser {% templatetag openvariable %} générerait {{.

7
Thomas Orozco

Je préférerais utiliser une solution qui utilise les deux balises Django {{}} ainsi que angularjs {{}} avec une section ou une balise de type verbatim. 

C’est simplement parce que vous pouvez modifier le fonctionnement d’angularjs (comme indiqué) via $ interpolateProvider.startSymbol $ interpolateProvider.endSymbol, mais si vous commencez à utiliser d’autres composants angularjs comme ui-bootstrap, vous constaterez que certains modèles sont déjà construits avec les balises angularjs standard {{}}. 

Par exemple, consultez https://github.com/angular-ui/bootstrap/blob/master/template/dialog/message.html

3
silviud

Si vous effectuez une interpolation côté serveur, la méthode correcte pour uniquement consiste à utiliser <>

$interpolateProvider.startSymbol('<{').endSymbol('}>');

Tout le reste est un vecteur XSS.

En effet, tout délimiteur angulaire non échappé par Django peut être saisi par l'utilisateur dans la chaîne interpolée. si quelqu'un définit son nom d'utilisateur comme "{{evil_code}}", Angular le fera fonctionner avec plaisir Si vous utilisez un caractère que Django échappe , cependant, cela n'arrivera pas.

0
Dan