2010-06-22 3 views
28

Ich versuche, ein etwas konsistentes Benennungsschema auf meinen HTML-Templates zu halten. I.e. index.html für main, delete.html für delete-Seite und so weiter. Aber die app_directories Loader scheint immer die Vorlage aus der App, die zuerst alphabetisch ist, zu laden.Django-Ansicht - Laden der Vorlage aus dem Aufruf der App zuerst

Gibt es eine Möglichkeit, zuerst im Verzeichnis templates der anrufenden App nach einer Übereinstimmung zu suchen?

Relevante Einstellungen in meinem 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'), 
) 

Ich habe versucht, die Reihenfolge der TEMPLATE_LOADERS, ohne Erfolg zu verändern.


bearbeiten wie von Ashok angefordert:

Dir Struktur jeder App:

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

in jeder views.py App:

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

können Sie zur Verfügung stellen, die die Struktur Ihres Verzeichnisses ‚Vorlagen‘ und einen Beispielcode, wie Sie laden/Rendern der Vorlage – Ashok

+0

Der app_directories loader mir ein wenig irreführend klingt. Ich hätte angenommen, dass es Vorlagen wie Sie aus dem richtigen Anwendungsverzeichnis laden würde. Ist es nicht der Sinn einer Django-App, getrennte Slices erstellen zu können? – Adam

Antwort

43

Der Grund dafür ist, dass der app_directories Loader im Wesentlichen das Gleiche ist wie das Hinzufügen der Apps Vorlagenordner für die Einstellung TEMPLATE_DIRS, z. wie

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

Das Problem dabei ist, dass, wie Sie erwähnt, wird die index.html immer in app1/templates/index.html statt jede andere App. Es gibt keine einfache Lösung, dieses Verhalten magisch zu beheben, ohne den app_directories Loader zu modifizieren und Introspektion zu verwenden oder App-Informationen weiterzugeben, was ein wenig kompliziert wird. Eine einfachere Lösung:

  • Ihre settings.py halten, wie sie ist
  • ein Unterverzeichnis hinzufügen in jedem Vorlagenordner des App mit dem Namen der App
  • Verwenden Sie die Vorlagen in Ansichten wie ‚app1/index.html 'oder 'app2/index.html'

Für ein konkretes Beispiel:

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

Dann in den Ansichten:

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

könnten Sie schreiben sogar einen Wrapper Voranstellen den Namen der Anwendung auf alle Ihre Ansichten zu automatisieren und sogar erweitert werden, dass könnte Innerlichkeit zu verwenden, zB:.

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

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

Der _____ Name _____ split (“. ") [- 2] geht davon aus, dass die Datei innerhalb eines Pakets liegt, also wird es sich z 'app1.views' in 'app1', um dem Vorlagennamen voranzukommen. Dies setzt auch voraus, dass ein Benutzer Ihre App niemals umbenennt, ohne auch den Ordner im Templates-Verzeichnis umzubenennen, was möglicherweise keine sichere Annahme ist und in diesem Fall nur den Namen des Ordners im Templates-Verzeichnis fest codiert.

+1

Das ist so ziemlich das einzige, was ich von CakePHP vermisse :) Ich hoffe, dass sie es eines Tages hinzufügen. – jmagnusson

+0

Es ist eine gute Problemumgehung für eine defekte Django-Funktion (es ist ein Kompromiss für ein sehr einfach zu erweiterndes Vorlagensystem); aber es ist immer noch verpflichtet, den Ordner "appname" zu Ihrem App-Vorlagenordner hinzuzufügen, und "appname" ist möglicherweise nicht der, den Sie in Ihrem Projekt verwenden möchten ... – Stefano

+0

Dies ist eine nette und einfache Lösung, solange es keine gibt 't verschachtelte apps ...;) –

3

Der app_loader sucht nach Vorlagen in Ihren Anwendungen, damit sie in INSTALLED_APPS angegeben werden. (http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types).

Mein Vorschlag ist, den Namen Ihrer Vorlagendatei mit dem App-Namen vorzuverlegen, um diese Namenskonflikte zu vermeiden.

Zum Beispiel würde die Vorlage dir für app1 wie folgt aussehen:

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

Danke Chris! Nach langer Suche war die Antwort für mich - die App war nicht in INSTALLED_APPS gelistet, daher wurde nur im Basis-Templates-Ordner gesucht, nicht im lokalen Ordner der App. Für mich ist das, weil meine settings.py und mein local_settings.py nicht synchron waren, weil nur die settings.py versionsgesteuert ist, nach einem Pull und Update hatte es eine neue App, aber meine local_settings.py hat es überschrieben. –

7

Ich weiß, das ein alter Thread, aber ich habe etwas wiederverwendbar, die für einfachere Namespacing ermöglicht. Sie könnten Folgendes als Vorlagenlader laden. Es wird appname/index.html in appname/templates/index.html finden.

Gist verfügbar hier: 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

Nun funktioniert es genau wie 'django.template.loaders.app_directories.Loader' in Django 1.5.x. Und das Problem ist immer noch nicht gelöst. – shailenTJ

Verwandte Themen