2010-10-19 14 views
42

Si desea anular una plantilla que viene con una aplicación en django (en app/templates/app /), cree una plantilla del mismo nombre en otro directorio, que el cargador de plantillas verifica antes de la plantilla de la plantilla dir. Si solo desea sobrescribir ciertos bloques de la plantilla, también debe copiar toda la plantilla y cambiar el anuncio de ese bloque, que en realidad no es muy SECO.Django: redefiniendo Y ampliando una plantilla de aplicación

¿Alguien sabe una manera de anular la plantilla orginial, mientras que al mismo tiempo la extiende, por lo que solo tiene que anular el bloque específico que desea cambiar? (Lo está haciendo esto sin cambiar el nombre de la plantilla, ya que en algunos casos puede que tenga que cambiar la vista para que funcione con otra plantilla)

EDIT: Como Adam Taylor señaló en los comentarios de Django 1.9 on este es posible sin ningún hackeo.

+0

@paulo: Por lo que yo sé que hay, por supuesto, documentos sobre Sustituyendo plantillas de la aplicación en general, ya que esta es la práctica diaria, pero nunca vi nada acerca de extender una plantilla que tiene el mismo nombre. Si sabes que está en los documentos, dirígeme a ese lugar ... –

+0

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

+1

El enfoque solo funciona para plantillas de administración específicas de la aplicación, ya que van a un camino diferente al original.Imagina que esa es la razón por la cual esto está en el * admin * doc y no en el general;) –

Respuesta

34

Creo que la respuesta de this related question es pertinente; actualmente, la mejor solución parece ser utilizar un cargador de plantillas personalizado desde el django-apptemplates package on PyPI, por lo que puede usar pip para instalarlo (por ejemplo, pip install django-apptemplates).

El cargador de plantillas le permite extender una plantilla en una aplicación específica; por ejemplo, para extender la página de índice de la inteface de administración, deberá añadir

'apptemplates.Loader', 

a su lista de TEMPLATE_LOADERSsettings.py, y utilizar

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

en sus plantillas.

+1

Un proyecto en el que estoy usando este fragmento de código para resolver este problema exacto. Me sorprende que más personas no lo alcancen: una aplicación que quiere modificar partes de las páginas existentes. –

+2

Creo que este es un problema común, pero las personas lo necesitan duplicando las plantillas completas. Si alguien lo ha intentado, anulando y extendiendo a menudo termina con infinita recursividad. El problema se describe en este ticket: https://code.djangoproject.com/ticket/15053 – Nagyman

-1

[Actualización]

He leído mal la pregunta, mi respuesta original se aplica sólo a la aplicación de administración, que tiene un mecanismo de extensión del molde incorporado. Para otra aplicación que carece de dicho mecanismo, simplemente me gustaría mover las plantillas originales en lugar de jugar con cargadoras de plantillas personalizadas, como aconseja la respuesta elegida. Si le preocupa el bifurcación, también puede implementar un mecanismo de extensión y contribuir al proyecto original si cree que vale la pena.


[respuesta original]

Directamente de la multa manual: Debido al diseño modular de las plantillas de administración, por lo general es necesario ni aconsejable sustituir una plantilla entera. Casi siempre es mejor anular solo la sección de la plantilla que debe cambiar.

Para continuar con el ejemplo anterior, queremos agregar un nuevo enlace al lado de la herramienta Historial para el modelo de página. Después de mirar change_form.html, determinamos que solo tenemos que anular el bloque de herramientas de objeto. Por lo tanto aquí está nuestro nuevo 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 %} 

Y eso es todo! Si colocamos este archivo en el directorio templates/admin/my_app, nuestro enlace aparecerá en el formulario de cambios de cada modelo.

+0

Gracias por publicar esto, pero mi pregunta no es sobre plantillas de ADMIN. Estoy buscando hacer algo como esto con plantillas (frontend) que, por ejemplo. vengo con una aplicación de terceros, donde probablemente solo quiera cambiar un bloque, y copiar todo el resto para anular solo una parte me parece una violación DRY ... –

+1

@lazerscience: es el mismo proceso, excepto en su plantilla directorio debe adherirse a la misma estructura de directorios que las plantillas que está anulando. Compruebe: http://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loader.select_template –

+4

No creo que esto todavía responda la pregunta original. Digamos que 'niceapp.views.index()' usa la plantilla 'niceapp/index.html'. Si quiero usar la vista original pero personalizar la plantilla, puedo crear una 'niceapp/index.html' en un directorio' templates' de mi proyecto o de mi propia aplicación. Pero, ¿cómo ampliar el original y anular solo algunos bloques, y no copiar toda la plantilla? Decir '{% extender" niceapp/index.html "%}' aparentemente no hace el trabajo. – akaihola

2

En la wiki de Django, Simon Willison presenta a trick para lograr el efecto de "plantilla autoextendida". Sin embargo, no es directamente aplicable si está usando el cargador de plantillas app_directories.

Hacer un enlace simbólico de directorios de plantillas de aplicaciones dentro de un nuevo directorio podría ser un truco.

+0

Gracias, eso tampoco es el 100% de lo que estaba buscando, pero no creo que puedas acercarte más; ya estaba haciendo algo similar al personalizar templatesd para diferentes sitios! –

-3

Una forma sencilla de hacerlo es la siguiente:

Digamos que desea ampliar y anular django/contrib/admin/templates/admin/change_form.html.

Primero, copie el change_form.html original en el directorio de plantillas de su aplicación y renómbrelo como algo como myapp/templates/admin/original_change_form.html. (También podría hacer esto como un enlace simbólico).

En segundo lugar, cree su propio change_form.html en myapp/templates/admin. En la parte superior, coloque lo siguiente:

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

¡Simple!

+0

En realidad, no es una solución incorrecta, especialmente si su sistema admite enlaces simbólicos. – Flimm

6

Como una actualización ya que esta parece ser una pregunta popular. He usado el overextends app sin ningún problema. Proporciona una nueva palabra clave sobreextensiones que permite extender plantillas con el mismo nombre.

Y es fácil de instalar con pip:

pip install -U django-overextends 
+0

guau, ¡esto es súper fácil y ligero! ¡quiéralo! ¡Gracias! –

+0

FYI La última versión para Django 1.4 fue 0.3.2, las últimas necesitan 1.7 –

3

Django 1.9 y posteriores tiene this feature:

Django cargadores de plantillas pueden ahora ampliar las plantillas de forma recursiva.

lo que puede tener un archivo de app1 con contenidos como esto:

app1/templates/example/foobar.html:

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

y se puede extender con un archivo de app2 (notar que el nombre de la plantilla example/foobar.html es lo mismo):

app2/templates/example/foobar.html:

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

El resultado final debe ser:

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

He intentado exactamente esta configuración y parece que no funciona. – HoHo

+0

@HoHo ¿qué versión de Django estás usando? – Flimm

+0

Estoy usando 1.10 - si 'app1' tiene un conjunto de plantillas interrelacionadas (digamos' app1/templates/app1/base.html', que se extiende por 'app1/templates/app1/subfolder/subsitio.html') , ¿cómo deberían las plantillas 'app2' ampliar ambas plantillas? Pensé que usar su método, donde uno replica la jerarquía de la carpeta y los nombres de archivo en 'app1', funcionaría, pero no parece. – HoHo

Cuestiones relacionadas