33 votes

Vue Django - charger d'abord le modèle à partir du répertoire de l'application appelante.

J'essaie de garder un schéma de dénomination assez cohérent sur mes modèles HTML. Par exemple, index.html pour la page principale, delete.html pour la page de suppression et ainsi de suite. Mais le app_directories loader semble toujours charger le modèle de l'application qui est en tête de l'ordre alphabétique.

Existe-t-il un moyen de toujours vérifier s'il y a une correspondance dans l'application appelante ? templates le répertoire en premier ?

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 des TEMPLATE_LOADERS sans succès.


Modifier comme demandé par Ashok :

La structure de chaque application :

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

Dans le fichier views.py de chaque 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())

55voto

Daniel Points 1032

La raison en est que le chargeur app_directories revient essentiellement à ajouter le dossier de modèle de chaque application au paramètre TEMPLATE_DIRS, par exemple de la manière suivante

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, comme vous l'avez mentionné, l'index.html sera toujours trouvé dans app1/templates/index.html au lieu d'une autre application. Il n'y a pas de solution facile pour corriger magiquement ce comportement sans modifier le chargeur app_directories et utiliser l'introspection ou transmettre des informations sur les applications, ce qui devient un peu compliqué. Une solution plus simple :

  • Gardez votre settings.py tel quel
  • Ajoutez un sous-répertoire dans le dossier des modèles de chaque application avec le nom de l'application.
  • Utilisez les modèles dans des 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 pourriez même écrire un wrapper pour automatiser l'ajout du nom de l'application à toutes vos vues, et même cela pourrait être étendu pour 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())

L'option _____name_____.split(".")[-2] part du principe que le fichier fait partie d'un paquetage, ce qui transforme par exemple 'app1.views' en 'app1' à ajouter au nom du modèle. Cela suppose également qu'un utilisateur ne renommera jamais votre application sans renommer également le dossier dans le répertoire des modèles, ce qui peut ne pas être une hypothèse sûre à faire et dans ce cas, il suffit de coder en dur le nom du dossier dans le répertoire des modèles.

7voto

hidde-jan Points 71

Je sais que c'est un vieux sujet, mais j'ai créé quelque chose de réutilisable, qui permet de simplifier l'espacement des noms. Vous pouvez charger ce qui suit comme un Template Loader. Il trouvera appname/index.html en appname/templates/index.html .

Gist disponible 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))

6voto

Chris Lawlor Points 10033

L'app_loader recherche les 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 ).

Je vous suggère de faire précéder le nom de votre fichier modèle du nom de l'application pour éviter ces conflits de noms.

Par exemple, le répertoire de modèle pour l'application 1 ressemblerait à ceci :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X