Je veux utiliser le même {% block%} deux fois dans le même modèle django. Je veux que ce bloc apparaisse plus d'une fois dans mon modèle de base:
# base.html
<html>
<head>
<title>{% block title %}My Cool Website{% endblock %}</title>
</head>
<body>
<h1>{% block title %}My Cool Website{% endblock %}</h1>
</body>
</html>
Et puis prolongez-le:
# blog.html
{% extends 'base.html' %}
{% block title %}My Blog{% endblock %}
# pictures.html
{% extends 'base.html' %}
{% block title %}My Pictures{% endblock %}
# cats.html
{% extends 'base.html' %}
{% block title %}My Cats{% endblock %}
J'obtiendrai une exception, car Django souhaite que le bloc n'apparaisse qu'une seule fois:
TemplateSyntaxError à /
La balise 'block' avec le nom 'title' apparaît plus d'une fois
Une solution rapide et sale consisterait à dupliquer le titre du bloc dans title1 et title2 :
# blog.html
{% extends 'base.html' %}
{% block title1 %}My Blog{% endblock %}
{% block title2 %}My Blog{% endblock %}
Mais c'est une violation du principe DRY . Ce serait très difficile car j'ai beaucoup de modèles héritiers, et aussi parce que je ne veux pas aller en enfer ;-)
Y a-t-il une astuce ou une solution à ce problème? Comment puis-je répéter le même bloc dans mon modèle, sans dupliquer tout le code?
django
django-templates
dry
David Arcos
la source
la source
Réponses:
Je pense que l'utilisation du processeur de contexte est dans ce cas exagéré. Vous pouvez facilement faire ceci:
puis:
et ainsi de suite ... Ressemble à DRY-compatible.
la source
h1
contenu à l'intérieur du bloc qui définit letitle
. Ou un bloc qui définit une partie du fichiertitle
.Utilisez le plugin de macros de modèle Django:
https://gist.github.com/1715202 (django> = 1.4)
ou
http://www.djangosnippets.org/snippets/363/ (django <1.4)
django> = 1,4
et
django <1,4
et
la source
Vous ne voulez probablement pas utiliser un bloc mais plutôt simplement utiliser une variable:
Vous définissez ensuite le titre dans le contexte.
la source
Voici une façon que j'ai découverte en essayant de faire la même chose moi-même:
Nécessite malheureusement un fichier supplémentaire, mais ne nécessite pas que vous passiez le titre de la vue.
la source
<tr>
rangée était plutôt complexe.vous pouvez utiliser
{% include subtemplate.html %}
plusieurs fois. ce n'est pas la même chose que les blocs, mais ça fait l'affaire.la source
include
c'est plus lent queblock
. docs.djangoproject.com/en/1.10/topics/performance/…Il y a quelques discussions ici: http://code.djangoproject.com/ticket/4529 De toute évidence, l'équipe de base de django rejette ce ticket car ils pensent que ce n'est pas un scénario couramment utilisé, mais je ne suis pas d'accord.
Le bloc de répétition est une implémentation simple et propre pour cela: https://github.com/SmileyChris/django-repeatblock
les macros de modèles en sont une autre, mais l'auteur a mentionné qu'elles n'avaient pas été soigneusement testées: http://www.djangosnippets.org/snippets/363/
J'ai utilisé repeatblock.
la source
En tant que mise à jour pour quiconque rencontre cela, j'ai pris l'extrait de code mentionné ci-dessus et l'ai transformé en une bibliothèque de balises de modèles, django-macros, rend les macros plus puissantes et implémente également un modèle de bloc répété explicitement: django-macros .
la source
Voici une solution légère similaire à la réponse de balise ci-dessus
do_set
etdo_get
modèle. Django vous permet de passer tout le contexte du modèle dans une balise qui peut vous permettre de définir une variable globale.base.html:
page.html:
tag personnalisé (j'ai eu l'idée ici: https://stackoverflow.com/a/33564990/2747924 ):
N'oubliez pas non plus
{% load %}
vos balises personnalisées ou ajoutez-les à la liste intégrée des options de modèle afin de ne pas avoir à les charger dans chaque modèle. La seule limitation de cette approche est le{% define %}
doit être appelé à partir d'une balise de bloc car les modèles enfants ne rendent que les balises de bloc qui correspondent aux balises parentes. Je ne sais pas s'il existe un moyen de contourner cela. Assurez-vous également que l'define
appel arrive avant d'essayer de l'utiliser évidemment.la source
En vous basant sur la suggestion de Van Gale, vous pouvez créer des balises get et set en ajoutant ce qui suit à votre fichier templatetags.py:
Ensuite, définissez les valeurs dans un modèle via
{% set foo %}put data here{% endset %}
et récupérez-les via{% get foo %}
un autre.la source
Moi aussi, j'ai rencontré le même besoin de répéter {% block%} dans mes fichiers de modèle. Le problème est que je veux qu'un Django {% block%} soit utilisé dans les deux cas d'un conditionnel Django, et je veux que le {% block%} soit écrasable par les fichiers suivants qui peuvent étendre le fichier actuel. (Donc dans ce cas, ce que je veux est définitivement plus un bloc qu'une variable parce que je ne le réutilise pas techniquement, il apparaît juste à chaque extrémité d'un conditionnel.
Le problème:
Le code de modèle Django suivant entraînera une erreur de syntaxe de modèle, mais je pense que c'est un "souhait" valide d'avoir un {% block%} défini réutilisé dans un conditionnel (IE, pourquoi l'analyseur Django valide la syntaxe aux DEUX extrémités d'un conditionnel, ne devrait-il pas seulement valider la condition VRAIE?)
La solution:
Vous pouvez utiliser un {% include%} pour insérer conditionnellement un {% block%} plusieurs fois. Cela a fonctionné pour moi car le vérificateur de syntaxe de Django n'inclut que TRUTHY {% include%}. Voir le résultat ci-dessous:
la source
J'utilise cette réponse pour garder les choses au sec.
la source
Il existe deux solutions simples pour cela.
Le plus simple est de mettre votre titre dans une variable de contexte. Vous définiriez la variable de contexte dans votre vue.
Si vous utilisez quelque chose comme des vues génériques et que vous n'avez pas de views.py pour les images, les chats, etc., vous pouvez opter pour une balise de modèle personnalisée qui définit une variable dans le contexte .
Suivre cette route vous permettrait de faire quelque chose comme:
Puis dans votre base.html:
la source
Any variable set in the context will only be available in the same block of the template in which it was assigned. This behavior is intentional; it provides a scope for variables so that they don’t conflict with context in other blocks.
La réponse sélectionnée fait allusion à une solution de contournement simple pour envelopper une balise dans une autre dans le modèle enfant pour leur donner à tous les deux la même valeur. J'utilise ceci pour des images sociales comme ça.
Modèle enfant:
Puis chez le parent
base.html
:la source
En brindille, vous pouvez faire ceci comme:
la source