2010-10-19 19 views
42

Wenn Sie eine mit Django erstellte Vorlage überschreiben möchten (in app/templates/app /), erstellen Sie eine Vorlage mit dem gleichen Namen in einem anderen Verzeichnis, das der Vorlagenlader prüft vor dem Template-Verzeichnis der App Wenn Sie nur bestimmte Blöcke der Vorlage überschreiben möchten, müssen Sie auch die gesamte Vorlagenanzeige kopieren, um den Block zu ändern, der eigentlich nicht sehr DRY ist.Django: Überschreiben und Erweitern einer App-Vorlage

Kennt jemand eine Möglichkeit, die orginial Vorlage zu überschreiben, während es gleichzeitig erweitert, so dass Sie nur den bestimmten Block überschreiben müssen, den Sie ändern möchten? (Das Ding tut dies ohne den Namen der Vorlage zu ändern, weil in einigen Fällen Sie können die Ansicht ändern müssen, um es mit einer anderen Vorlage funktioniert)

EDIT: Als Adam Taylor wies aus Django 1.9 on in den Kommentaren aus diesem ist ohne irgendwelche Hacks möglich.

+0

@paulo: soweit ich weiß, gibt es natürlich docs ist die App-Vorlagen im Allgemeinen über überschreiben, da dies die tägliche Praxis ist, aber ich habe nie etwas über das Erweitern einer Vorlage, die denselben Name hat. Wenn Sie wissen, dass es in der Dokumentation ist, zeigen Sie mich bitte auf diesen Ort ... –

+0

http://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-vs-replacing-an-admin-template –

+1

Der Ansatz dort funktioniert nur für App-spezifische Admin-Vorlagen, da diese auf einen anderen Pfad als das Original gehen.Ich glaube, das ist der Grund, warum dies im * admin * doc und nicht im allgemeinen ist;) –

Antwort

34

Ich denke, die Antwort von this related question ist relevant; Derzeit scheint die beste Lösung zu sein, einen benutzerdefinierten Vorlagenlader von django-apptemplates package on PyPI zu verwenden, so dass Sie einfach pip verwenden können, um es zu installieren (z. B. pip install django-apptemplates).

Der Vorlagenlader ermöglicht es Ihnen, eine Vorlage in einer bestimmten App zu erweitern; beispielsweise die Index-Seite des Admin inteface zu erweitern, würden Sie

'apptemplates.Loader', 

auf Ihre TEMPLATE_LOADERS Liste in settings.py, hinzufügen und

{% extends "admin:admin/index.html" %} 

in Ihren Vorlagen verwenden.

+1

Ein Projekt, in dem ich bin, verwendet dieses Snippet, um genau dieses Problem zu lösen. Ich bin überrascht, dass mehr Leute es nicht tun: eine App, die Teile bestehender Seiten optimieren will. –

+2

Ich denke, das ist ein häufiges Problem, aber Menschen machen durch Duplizieren voller Vorlagen fällig. Wenn jemand versucht hat, endet das Überschreiben und Erweitern oft mit unendlicher Rekursion. Das Problem wird in diesem Ticket beschrieben: https://code.djangoproject.com/ticket/15053 – Nagyman

-1

[update]

ich die Frage falsch verstanden habe, gilt meine ursprüngliche Antwort nur auf die Admin-App, das einen integrierten Template-Erweiterungsmechanismus. Für andere App, die solchen Mechanismus fehlt, würde ich einfach die ursprünglichen Vorlagen forkeln, anstatt mit benutzerdefinierten Vorlagenladeprogrammen wie die ausgewählten Antwort-Ratgeber zu hantieren. Wenn Sie sich Sorgen um Gabeln machen, können Sie auch einen Erweiterungsmechanismus implementieren und zu dem ursprünglichen Projekt beitragen, wenn Sie es für sinnvoll halten.


[ursprüngliche Antwort]

Gerade vom feinen manual: Durch den modularen Aufbau des Admin-Templates, es ist in der Regel weder notwendig noch ratsam, eine ganze Vorlage zu ersetzen. Es ist fast immer besser, nur den Abschnitt der Vorlage zu überschreiben, den Sie ändern müssen.

Um das obige Beispiel fortzusetzen, möchten wir einen neuen Link neben dem Protokoll-Tool für das Seitenmodell hinzufügen. Nach dem Betrachten von change_form.html stellen wir fest, dass wir nur den Objekt-Werkzeugblock überschreiben müssen. Deshalb hier ist unser neues change_form.html:

{% extends "admin/change_form.html" %} 
{% load i18n %} 
{% block object-tools %} 
{% if change %}{% if not is_popup %} 
    <ul class="object-tools"> 
    <li><a href="history/" class="historylink">{% trans "History" %}</a></li> 
    <li><a href="mylink/" class="historylink">My Link</a></li> 
    {% if has_absolute_url %} 
     <li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink"> 
      {% trans "View on site" %}</a> 
     </li> 
    {% endif%} 
    </ul> 
{% endif %}{% endif %} 
{% endblock %} 

Und das ist es! Wenn wir diese Datei im Verzeichnis templates/admin/my_app ablegen, erscheint unser Link auf dem Änderungsformular jedes Modells.

+0

Vielen Dank für das Posten, aber meine Frage bezieht sich nicht auf ADMIN-Vorlagen. Ich suche etwas mit (Frontend) Templates, die zB. Kommen Sie mit einer Drittanbieter-App, wo ich wahrscheinlich nur einen Block ändern wollen, und Kopieren der gesamte Rest, um nur ein Teil außer Kraft zu setzen sieht aus wie ein Verstoß gegen mich DRY ... –

+1

@lazerscience: Es ist der gleiche Prozess, außer in Ihrer Vorlage Verzeichnis sollten Sie die gleiche Verzeichnisstruktur wie die Vorlagen beibehalten, die Sie überschreiben. Überprüfen Sie: http://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loader.select_template –

+4

Ich glaube nicht, dass dies immer noch die ursprüngliche Frage beantwortet. Sagen Sie, dass 'niceapp.views.index()' die Vorlage 'niceapp/index.html' verwendet. Wenn ich die Originalansicht verwenden, aber die Vorlage anpassen möchte, kann ich eine 'niceapp/index.html' in einem' templates' -Verzeichnis meines Projekts oder meiner eigenen App erstellen. Aber wie erweitert man das Original und überschreibt nur einige Blöcke und kopiert nicht die gesamte Vorlage? Der Aufruf von '{% extend" niceapp/index.html "%}' funktioniert anscheinend nicht. – akaihola

2

Im Wiki von Django präsentiert Simon Willison a trick, um den Effekt der "selbstausdehnenden Vorlage" zu erzielen. Es ist jedoch nicht direkt anwendbar, wenn Sie den Vorlagenlader app_directories verwenden.

Das Verknüpfen von Vorlagenverzeichnissen von Apps in einem neuen Verzeichnis könnte einen Trick darstellen.

+0

Danke, das ist auch nicht 100% was ich gesucht habe, aber ich glaube nicht, dass du näher kommen kannst; war bereits etwas Ähnliches bei der Anpassung von Templates für verschiedene Sites! –

-3

Eine einfache Möglichkeit, es zu tun, ist dies:

Sagen wir, Sie erweitern möchten, und überschreiben django/contrib/admin/templates/admin/change_form.html.

Kopieren Sie zuerst die ursprüngliche change_form.html in das Vorlagenverzeichnis Ihrer App und benennen Sie sie wie myapp/templates/admin/original_change_form.html um. (Sie könnten dies auch als Symlink machen.)

Zweitens, erstellen Sie Ihre eigene change_form.html in myapp/templates/admin. An der Spitze davon, setzen Sie die folgenden:

{% extends "admin/original_change_form.html" %} 

Einfach!

+0

Das ist eigentlich keine schlechte Lösung, besonders wenn Ihr System Symlinks unterstützt. – Flimm

6

Als Update scheint dies eine beliebte Frage zu sein. Ich habe das overextends app ohne irgendein Problem benutzt. Es bietet eine neue Schlüsselwörter überextens, die Vorlagen mit dem gleichen Namen erweitern können.

Und es ist leicht mit pip zu installieren:

pip install -U django-overextends 
+0

wow, das ist super einfach und leicht! Liebe es! Vielen Dank! –

+0

FYI Letzte Version für Django 1.4 war 0.3.2, letztere benötigen 1.7 –

3

Django 1.9 und später hat this feature:

Django Template Lader können nun Vorlagen rekursiv erweitern.

So können Sie eine Datei von app1 mit Inhalten wie diese:

app1/templates/example/foobar.html:

<p>I'm from app1</p> 
{% block main %}{% endblock %} 

Und Sie können es von app2 mit einer Datei erweitern (beachten Sie, dass der Template-Name example/foobar.html ist gleich):

app2/templates/example/foobar.html:

{% extends "example/foobar.html" %} 
{% block main %} 
    <p>I'm from app2</p> 
{% endblock %} 

Das Endergebnis sein sollte:

<p>I'm from app1</p> 
<p>I'm from app2</p> 
+0

Ich habe genau dieses Setup versucht und es scheint nicht zu funktionieren. – HoHo

+0

@HoHo welche Django Version verwendest du? – Flimm

+0

Ich benutze 1.10 - wenn 'app1' einen Satz von miteinander verknüpften Templates hat (sagen wir' app1/templates/app1/base.html', welches um 'app1/templates/app1/subfolder/subsite.html' erweitert wird) Wie sollten die Vorlagen "app2" beide Vorlagen erweitern? Ich dachte, Ihre Methode - wo man die Ordnerhierarchie und Dateinamen in "app1" repliziert - würde funktionieren, aber es scheint nicht zu funktionieren. – HoHo

Verwandte Themen