modèles django: inclure et étendre

109

Je voudrais fournir le même contenu dans 2 fichiers de base différents.

J'essaye donc de faire ceci:

page1.html:

{% extends "base1.html" %}
{% include "commondata.html" %}

page2.html:

{% extends "base2.html" %} 
{% include "commondata.html" %}

Le problème est que je n'arrive pas à utiliser à la fois les extensions et les inclusions. Y a-t-il un moyen de faire cela? Et sinon, comment puis-je accomplir ce qui précède?

commondata.html remplace un bloc spécifié à la fois dans base1.html et base2.html

Le but est de fournir la même page au format pdf et html, où le formatage est légèrement différent. La question ci-dessus simplifie cependant ce que j'essaie de faire, si je peux obtenir une réponse, cela résoudra mon problème.

Citoyen net
la source

Réponses:

110

Lorsque vous utilisez la balise de modèle étend, vous dites que le modèle actuel en étend un autre - qu'il s'agit d'un modèle enfant, dépendant d'un modèle parent. Django examinera votre modèle enfant et utilisera son contenu pour peupler le parent.

Tout ce que vous souhaitez utiliser dans un modèle enfant doit se trouver dans des blocs, que Django utilise pour peupler le parent. Si vous voulez utiliser une instruction d'inclusion dans ce modèle enfant, vous devez la mettre dans un bloc, pour que Django en fasse un sens. Sinon, cela n'a pas de sens et Django ne sait pas quoi en faire.

La documentation Django a quelques très bons exemples d'utilisation de blocs pour remplacer des blocs dans le modèle parent.

https://docs.djangoproject.com/en/dev/ref/templates/language/#template-inheritance

Matt Howell
la source
1
my commondata.html contient le bloc défini. Mais cela ne remplace pas le bloc du tempalte parent ... Si au lieu de faire un include, j'écris les données exactes deux fois dans page1.html et page2.html alors bien sûr cela fonctionne. Mais je veux tenir compte de cette similitude dans commondata.html.
Net Citizen du
Cela semble fonctionner, je me souviens avoir essayé cela, mais j'ai dû avoir une faute de frappe ou quelque chose à l'époque qui l'empêchait de fonctionner.
Net Citizen du
1
voir ma réponse ci-dessous pour savoir pourquoi cela n'a pas fonctionné pour moi la première fois, je vous laisse avec la réponse acceptée car vous avez répondu correctement à la question que j'ai posée.
Net Citizen du
80

À partir de la documentation Django:

La balise include doit être considérée comme une implémentation de "rendre ce sous-modèle et inclure le HTML", et non comme "analyser ce sous-modèle et inclure son contenu comme s'il faisait partie du parent". Cela signifie qu'il n'y a pas d'état partagé entre les modèles inclus - chaque inclusion est un processus de rendu complètement indépendant.

Donc Django ne récupère aucun bloc de votre commondata.html et il ne sait pas quoi faire avec les blocs extérieurs html rendus.

podshumok
la source
32

Cela devrait faire l'affaire pour vous: mettez la balise include à l'intérieur d'une section de bloc.

page1.html:

{% extends "base1.html" %}

{% block foo %}
   {% include "commondata.html" %}
{% endblock %}

page2.html:

{% extends "base2.html" %}

{% block bar %}
   {% include "commondata.html" %}
{% endblock %}
Pavel Černý
la source
1
Parfait. Travaille pour moi.
Trupti M Panchal
13

Plus d'informations sur les raisons pour lesquelles cela ne fonctionnait pas pour moi au cas où cela aiderait les futures personnes:

La raison pour laquelle cela ne fonctionnait pas est que {% include%} dans django n'aime pas les caractères spéciaux comme l'apostrophe fantaisie. Les données du modèle que j'essayais d'inclure ont été collées à partir de Word. J'ai dû supprimer manuellement tous ces caractères spéciaux, puis ils ont été inclus avec succès.

Citoyen net
la source
3

Vous ne pouvez pas extraire des blocs d'un fichier inclus dans un modèle enfant pour remplacer les blocs du modèle parent. Cependant, vous pouvez spécifier un parent dans une variable et avoir le modèle de base spécifié dans le contexte.

De la documentation :

{% extend variable%} utilise la valeur de variable. Si la variable correspond à une chaîne, Django utilisera cette chaîne comme nom du modèle parent. Si la variable est évaluée comme un objet Template, Django utilisera cet objet comme modèle parent.

Au lieu de séparer «page1.html» et «page2.html», placez- {% extends base_template %}le en haut de «commondata.html». Et puis, à votre avis, définissez base_templatecomme étant "base1.html" ou "base2.html".

émeri
la source
2

Ajouté pour référence aux futures personnes qui trouveront cela via google: vous pouvez consulter la balise {% overextend%} fournie par la bibliothèque mezzanine pour des cas comme celui-ci.

Ted
la source
1

Edit 10 décembre 2015 : Comme indiqué dans les commentaires, ssi est obsolète depuis la version 1.8. Selon la documentation:

Cette balise est obsolète et sera supprimée dans Django 1.10. Utilisez plutôt la balise include.


À mon avis, la bonne (meilleure) réponse à cette question est celle de podshumok , car elle explique pourquoi le comportement d'inclure lorsqu'il est utilisé avec l'héritage.

Cependant, j'ai été quelque peu surpris que personne n'ait mentionné la balise ssi fournie par le système de modèles Django, qui est spécialement conçu pour inclure un texte externe en ligne . Ici, en ligne signifie que le texte externe ne sera pas interprété, analysé ou interpolé, mais simplement "copié" à l'intérieur du modèle appelant.

Veuillez vous référer à la documentation pour plus de détails (assurez-vous de vérifier votre version appropriée de Django dans le sélecteur en bas à droite de la page).

https://docs.djangoproject.com/en/dev/ref/templates/builtins/#ssi

De la documentation:

ssi
Outputs the contents of a given file into the page.
Like a simple include tag, {% ssi %} includes the contents of another file
 which must be specified using an absolute path  in the current page

Méfiez-vous également des implications de sécurité de cette technique et également de la définition ALLOWED_INCLUDE_ROOTS requise, qui doit être ajoutée à vos fichiers de paramètres.

jose.angel.jimenez
la source
1
Notez qu'à partir de la version 1.8, ssi est devenu obsolète en faveur d'Inclusion. https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#std:templatetag-include
Tim S.