2010-06-22 5 views
28

J'essaie de garder un schéma de nommage relativement cohérent sur mes templates HTML. C'est à dire. index.html pour principal, delete.html pour supprimer la page et ainsi de suite. Mais le chargeur app_directories semble toujours charger le modèle de l'application qui est alphabétiquement d'abord.Django view - charger le template depuis le répertoire de l'application appelant

Existe-t-il un moyen de toujours rechercher une correspondance dans le répertoire templates de l'application appelante?

paramètres pertinents dans mon 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'), 
) 

J'ai essayé de changer l'ordre de TEMPLATE_LOADERS, sans succès.


Modifier comme demandé par Ashok:

Structure Dir de chaque application:

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

Dans chaque de views.py de l'application:

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

peut vous fournir la structure de votre répertoire « templates » et un exemple de code de la façon dont vous chargez/rendu le modèle – Ashok

+0

Le chargeur de app_directories semble un peu trompeur pour moi. J'aurais supposé qu'il chargerait des modèles du bon répertoire d'applications juste comme vous. Après tout, le but d'une application django n'est-il pas de créer des tranches séparées? – Adam

Répondre

43

La raison est-ce que le chargeur app_directories est essentiellement le même que l'ajout de chaque application dossier de modèle au paramètre TEMPLATE_DIRS, par ex. comme

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

Le problème est que vous avez mentionné, le index.html sera toujours trouvée dans APP1/templates/index.html au lieu de toute autre application. Il n'y a pas de solution facile pour résoudre ce problème par magie sans modifier le chargeur app_directories et en utilisant l'introspection ou en transmettant des informations sur l'application, ce qui devient un peu compliqué. Une solution plus simple:

  • Gardez votre settings.py as-est
  • Ajouter un sous-répertoire dans le dossier de chaque application de modèles avec le nom de l'application
  • Utilisez les modèles dans les vues comme « app1/index.html »ou 'App2/index.html'

Pour un exemple plus concret:

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

Puis, dans les vues:

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

Vous pouvez même écrire un wrapper pour automatiser préfixer le nom de l'application à tous vos points de vue, et même qui pourrait être étendu à utiliser l'introspection, par exemple:.

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

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

Le _____ nom _____ split (». ") [- 2] suppose que le fichier se trouve dans un paquet, donc il tournera par exemple 'app1.views' dans 'app1' pour préfixer le nom du template. Cela suppose également qu'un utilisateur ne renommera jamais votre application sans renommer également le dossier dans le répertoire templates, ce qui peut ne pas être une hypothèse sûre et, dans ce cas, coder en dur le nom du dossier dans le répertoire templates.

+1

C'est à peu près la seule chose qui me manque de CakePHP :) J'espère qu'ils l'ajouteront un jour. – jmagnusson

+0

C'est une bonne solution de contournement pour une fonctionnalité de django cassée (c'est un compromis pour un système de template très simple à étendre); mais cela oblige toujours à ajouter le dossier 'appname' à votre dossier de modèle d'application, et 'appname' n'est peut-être pas celui que vous voulez utiliser dans votre projet ... – Stefano

+0

Ceci est une solution agréable et simple, tant qu'il y a 't imbriqué apps ...;) –

3

Le programme app_loader recherche des modèles dans vos applications afin qu'ils soient spécifiés dans votre INSTALLED_APPS. (http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types).

Ma suggestion est de préfabriquer le nom de votre fichier modèle avec le nom de l'application pour éviter ces conflits de nommage.

Par exemple, le répertoire modèle pour app1 ressemblerait à ceci:

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

Merci Chris! après une longue période de recherche la réponse pour moi était - l'application ne figurait pas dans INSTALLED_APPS, donc il regardait seulement dans le dossier des modèles de base, pas le dossier local de l'application. Pour moi, c'est parce que mes settings.py et mes local_settings.py étaient désynchronisés car le seul settings.py est contrôlé par la version, après une extraction et une mise à jour il y avait une nouvelle application, mais mon local_settings.py l'a écrasé. –

7

Je sais que c'est un vieux fil, mais je fait quelque chose réutilisable, qui permet de simplifier l'espace de nommage. Vous pouvez charger ce qui suit en tant que chargeur de modèle. Il trouvera appname/index.html dans appname/templates/index.html.

Contenu essentiel ici: 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

Eh bien cela fonctionne exactement comme 'django.template.loaders.app_directories.Loader' dans Django 1.5.x. Et le problème n'est toujours pas résolu. – shailenTJ

Questions connexes