2010-06-22 12 views
28

Intento mantener un esquema de nombres un tanto coherente en mis plantillas HTML. Es decir. index.html para main, delete.html para eliminar página y así sucesivamente. Pero el cargador app_directories siempre parece cargar la plantilla desde la aplicación que está en primer lugar alfabéticamente.Vista de Django: cargar la plantilla desde el directorio de la aplicación que llama primero

¿Hay alguna forma de comprobar siempre si hay una coincidencia en el directorio templates de la aplicación que realiza la llamada primero?

ajustes pertinentes en mi settings.py:

PROJECT_PATH = os.path.realpath(os.path.dirname(__file__)) 

TEMPLATE_LOADERS = (
    'django.template.loaders.app_directories.load_template_source', 
    'django.template.loaders.filesystem.load_template_source', 
) 
TEMPLATE_DIRS = (
    os.path.join(PROJECT_PATH, 'templates'), 
) 

He intentado cambiar el orden de TEMPLATE_LOADERS, sin éxito.


Editar conforme a lo solicitado por Ashok:

estructura Dir de cada aplicación:

templates/ 
    index.html 
    add.html 
    delete.html 
    create.html 
models.py 
test.py 
admin.py 
views.py 

En views.py de cada aplicación:

def index(request): 
    # code... 
    return render_to_response('index.html', locals()) 

def add(request): 
    # code... 
    return render_to_response('add.html', locals()) 

def delete(request): 
    # code... 
    return render_to_response('delete.html', locals()) 

def update(request): 
    # code... 
    return render_to_response('update.html', locals()) 
+1

le puede proporcionar la estructura de directorio de su 'plantillas' y un código de ejemplo de la forma en que va a cargar/representación de la plantilla – Ashok

+0

El cargador app_directories suena un poco engañoso para mí. Hubiera supuesto que cargaría plantillas desde el directorio de aplicaciones correcto al igual que usted. Después de todo, ¿no es el objetivo de una aplicación django crear divisiones separadas? – Adam

Respuesta

43

La razón de esto es que el cargador app_directories es esencialmente lo mismo que agregar cada aplicación carpeta de plantillas a la configuración TEMPLATE_DIRS, p. como

TEMPLATE_DIRS = (
    os.path.join(PROJECT_PATH, 'app1', 'templates'), 
    os.path.join(PROJECT_PATH, 'app2', 'template'), 
    ... 
    os.path.join(PROJECT_PATH, 'templates'), 
) 

El problema con esto es que como usted ha mencionado, el index.html siempre se encontrará en app1/templates/index.html en lugar de cualquier otra aplicación. No existe una solución fácil para corregir mágicamente este comportamiento sin modificar el cargador de los ejecutables de la aplicación y el uso de la introspección o la transmisión de la información de la aplicación, lo que se complica un poco. Una solución más fácil:

  • Mantenga su settings.py tal cual
  • Añadir un subdirectorio en la carpeta de plantillas de cada aplicación con el nombre de la aplicación
  • utilizar las plantillas en las vistas como 'app1/index.html "o 'app2/index.html'

Para un ejemplo más concreto:

project 
    app1 
     templates 
      app1 
       index.html 
       add.html 
       ... 
     models.py 
     views.py 
     ... 
    app2 
     ... 

Luego, en los puntos de vista:

def index(request): 
    return render_to_response('app1/index.html', locals()) 

Incluso se podría escribir un envoltorio para automatizar anteponiendo el nombre de la aplicación a todos sus puntos de vista, e incluso que podría extenderse a utilizar la introspección, por ejemplo:.

def render(template, data=None): 
    return render_to_response(__name__.split(".")[-2] + '/' + template, data) 

def index(request): 
    return render('index.html', locals()) 

El _____ nombre _____ división (". ") [- 2] asume que el archivo está dentro de un paquete, por lo que cambiará, por ejemplo 'app1.views' en 'app1' para anteponer al nombre de la plantilla. Esto también supone que un usuario nunca cambiará el nombre de su aplicación sin cambiar el nombre de la carpeta en el directorio de plantillas, lo que puede no ser una suposición segura y, en ese caso, solo codificará el nombre de la carpeta en el directorio de plantillas.

+1

Esto es más o menos lo único que extraño de CakePHP :) Espero que lo agreguen algún día. – jmagnusson

+0

Es una buena solución para una característica de django rota (es un compromiso para un sistema de plantillas muy simple de extender); pero todavía obliga a agregar la carpeta 'appname' a la carpeta de la plantilla de la aplicación, y 'appname' podría no ser el que desea usar en su proyecto ... – Stefano

+0

Esta es una solución sencilla y sencilla, siempre que no haya 'aplicaciones anidadas ...;) –

3

El app_loader busca plantillas dentro de sus aplicaciones para que estén especificadas en su INSTALLED_APPS. (http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types).

Mi sugerencia es introducir el nombre de su archivo de plantilla con el nombre de la aplicación para evitar estos conflictos de nomenclatura.

Por ejemplo, el directorio de plantilla para app1 se vería así:

templates/ 
    app1_index.html 
    app1_delete.html 
    app1_add.html 
    app1_create.html 
+0

¡Gracias, Chris! después de un largo tiempo de búsqueda, la respuesta fue: la aplicación no figuraba en INSTALLED_APPS, por lo tanto, solo buscaba en la carpeta de plantillas base, no en la carpeta local de la aplicación. Para mí, esto es porque mi settings.py y mi local_settings.py no estaban sincronizados porque solo el settings.py está controlado por la versión, después de una extracción y actualización tenía una nueva aplicación, pero mi local_settings.py lo sobrescribió. –

7

Sé que esto es un hilo viejo, pero hizo algo reutilizable, que permite espacios de nombre del más simple. Puede cargar lo siguiente como un Cargador de plantillas. Encontrará appname/index.html en appname/templates/index.html.

Gist disponible aquí: https://gist.github.com/871567

""" 
Wrapper for loading templates from "templates" directories in INSTALLED_APPS 
packages, prefixed by the appname for namespacing. 

This loader finds `appname/templates/index.html` when looking for something 
of the form `appname/index.html`. 
""" 

from django.template import TemplateDoesNotExist 
from django.template.loaders.app_directories import app_template_dirs, Loader as BaseAppLoader 

class Loader(BaseAppLoader): 
    ''' 
    Modified AppDirecotry Template Loader that allows namespacing templates 
    with the name of their app, without requiring an extra subdirectory 
    in the form of `appname/templates/appname`. 
    ''' 
    def load_template_source(self, template_name, template_dirs=None): 
     try: 
      app_name, template_path = template_name.split('/', 1) 
     except ValueError: 
      raise TemplateDoesNotExist(template_name) 

     if not template_dirs: 
      template_dirs = (d for d in app_template_dirs if 
        d.endswith('/%s/templates' % app_name)) 

     return iter(super(Loader, self).load_template_source(template_path, 
       template_dirs)) 
+1

Bueno, funciona exactamente como 'django.template.loaders.app_directories.Loader' en Django 1.5.x. Y el problema aún no está resuelto. – shailenTJ

Cuestiones relacionadas