Order of finding static files and templates in django-apps - django

For example I have 2 apps in my django project with templates and static files with identical subpath:
app1 /
static /
style.css
templates /
index.html
app2 /
static /
style.css
templates /
index.html
than, in settings.py I added this two apps:
INSTALLED_APPS = (
'app1',
'app2',
)
now I use in some way 'style.css' and 'index.html' in templates, e.g.
{% include 'index.html' %}
so, question is:
Does Django guarantee that when I reference to 'style.css' or 'index.html' will be used files from app2 subdirectories?
Is it any other way to point Django preferable variants of files in such situation?

As per documentation, first match wins:
Duplicate file names are by default resolved in a similar way to how
template resolution works: the file that is first found in one of the
specified locations will be used.
https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#django-admin-collectstatic
Now, when you tell Django to collect static files or render templates, Django asks special "finders" in order they are defined in your configuraiton for specified resource.
Default order for static files is "FileSystemFinder" that searches STATICFILES_DIRS in order they are added in it. If FileSystemFinder fails to find file in those dirs, Django uses next finder set, the "AppDirectoriesFinder" that searches in "static" subdirectories in your apps directories.
Same mechanic is applied to templates. When you tell Django to render "index.html", it first asks "filesystem.Loader" find template named like that in directories defined in TEMPLATE_DIRS. If search fails, Django asks next template loader, "app_directories.Loader" that searches template dirs in applications "templates" subdirs.
To answer your question, because app1 is registered before app2, Django will use it's style.css and index.html instead of ones coming from app2. If you want to change this behaviour, put app2 above app1 in your installed apps setting.
Documentation:
https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loaders.app_directories.Loader

Related

Why did I get Template does not exist error, though it appears Django offers flexibility with respect to folder structure?

I have read several posts here where people discussed their preferred directory structure to keep various files of their Django project. But I get a file-does-not-exist error if I put my templates in the inner my_project folder instead of the outer my_project folder which contains the manage.py file. Is there some config file that specifies the default location of the templates (and other files)?can you please help me with the command change if I put templates in the inner (sub) folder? I just began my first Django project and would appreciate your help.
Ok, django looks for your templates at default places. I recommend you put your html files there (as a beginner).
Default places are:
- my_site_project/
-- templates/
--- base.html
--- navbar.html
--- footer.html
-- my_app1/
--- templates/
---- my_app1/
----- index_app1.html
----- about_app1.html
-- manage.py
If you put a general templates/ folder inside your project, same folder as your manage.py, those templates will be pulled.
If you want app specific templates the convention is to put a folder inside your app, again called templates/. This can lead to overlap if you put index.html inside your app-templates and an index.html inside your general templates/. Therefore you need to namespace the templates of your app. Create the app; create a folder called templates/ inside it; inside just created templates/folder you create another folder called my_app1; in that folder create your .html files.
Read the tutorial here. It is probably easier to understand than my jibberish. It is the official django tutorial.
A part of it:
First, create a directory called templates in your polls directory.
Django will look for templates in there.
Your project’s TEMPLATES setting describes how Django will load and
render templates. The default settings file configures a
DjangoTemplates backend whose APP_DIRS option is set to True. By
convention DjangoTemplates looks for a “templates” subdirectory in
each of the INSTALLED_APPS.
You can, in your settings.py via DIRS, specify where django looks for your templates. Although as a beginner I do not know why you should not stick to the conventions first.

Standard for application-specific template directories in Django?

I guess this is a question related to best practises in Django development.
I'm trying to build a web service with a main page (base.html) that contains multiple apps. I would like to make the apps self-contained, so I've made a templates directory in each app, and would also like to take advantage of the template inheritance feature of Django to make this whole thing as fluid as possible.
Now my concern is, where should I put the base.html in my project, so that the system knew where to find it?
Also, what changes should I make in the settings.py file in order for the system to be able to connect the templates? Is there a standard or a known method that takes minimal effort for this sort of arrangement?
You can put the templates folder in the project folder (ie folder contains settings.py).
as #danialroseman said, you just need to update the DIRS in TEMPLATES variable in settings.py. Let the project folder be myproject(ie folder contains settings.py)::
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
### ADD YOUR DIRECTORY HERE LIKE SO:
'DIRS': [ os.path.join(BASE_DIR,'myproject', 'templates')],
...
you dont need to create a seperate app.
One common design pattern that I have both seen and used is to have a centralized "app" as a part of your project that contains all the shared "stuff" you care to use in other applications. So you might have the following directory structure:
base/
static/
css/
common.css
js/
common.js
templates/
base.html
myapp1/
urls.py
views.py
templates/
...
myapp2/
urls.py
views.py
templates/
...
myproject/
settings.py
urls.py
Now you just include the "base" application just like any other, and you put shared stuff inside it. Other applications can refer to templates that live there, and can include any common libraries that you may want to share.
In settings.py:
INSTALLED_APPS = ['base', 'myapp1', 'myapp2']
There's no need for a central app for this. The TEMPLATES setting also includes an option for DIRS, which is a list of directories that will always be searched. So you can set this to an appropriate directory - eg os.path.join(BASE_DIR, 'templates') and put your non-app-specific templates such as base.html there.

Should my Django site's main page be an app?

I have finished reading the Django official tutorial which teaches how to create a simple polls app, which is the way they chose to teach beginners the Django basics.
My question is, now that I know how to make a simple app and want to create my own website (using Django), should the main (front) page of my website, be an app as well? If so, how do people usually call it and configure it? I mean, it should do nothing but render a html template, so why make it so complicated? If not, where do I put all the static files and how do I reference them? I am a bit confused and could use your help. Maybe I misunderstood Django's main use?
You can create your templates and static files in the root project folder where your manage.py file lives. In the root folder create the following folders:
templates (for HTML)
static (for CSS, JS and images)
In your settings.py file, make these variables look like this:
TEMPLATES = [
{
...
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
...
},
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
Note: STATICFILES_DIRS variable is initially not present in the settings.py file, but you can add that by your own. Django, by default, finds static files in the static directory of each app. If you want Django to read the static directory you created in the project root, you need to add this variable. Django official documentation reference: https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-STATICFILES_DIRS
To render these templates you can create views.py in the directory where your settings.py file lives and add the route in urls.py in the same folder.
This is one of the several ways to achieve what you want. Hope you won't need to plug these templates (eg, your home page) to or say use these templates in any other project, otherwise do as Timmy suggested in the comment on your post.
I usually start with 3 apps (call them whatever you want):
layout - basic layout: some common static files and a basic-template (other templates extend this one, main purpose is to
include a common html <head> ). Also contains the home-page and some other simple pages.
config - contains the project settings / configuration, and the main urls.py (and in my case also wsgi.py)
myapp - the actual app I want to create.
This nicely separates functionalities. Often I can just re-use the base app for other projects.
$ ./manage.py startproject config
$ ./manage.py startapp layout
$ ./manage.py startapp myapp

Django cms project for OpenShift. Where to place static files?

I am working on a django-cms based web site but having trouble with the static files. As I am going to deploy the site to OpenShift, I have used the django-example to construct the site (https://github.com/openshift/django-example). This way I ended up with the following overall structure of my django project:
root_folder
wsgi
media
static
my_project
my_app
templates
So as you see, it's a bit different from the standard Django dir structure. Django docs (https://docs.djangoproject.com/en/1.8/howto/static-files/) has told me the following:
Include django.contrib.staticfiles in INSTALLED_APPS: Done
Define a static url, e.g. STATIC_URL = '/static/‘: Done
Use static template tag to refer to static files, e.g. {% static "my_app/myexample.jpg" %}: Done
Furthermore, the static root is defined as
STATIC_ROOT = os.path.join(WSGI_DIR, 'static')
where WSGI_DIR points to the folder named wsgi.
I keep getting 404s in my dev environment where I use Debug=True, when I try to refer to the static files from my base template. I have tried to place them in the following locations with no luck:
/wsgi/static/
/wsgi/static/my_app/
/wsgi/my_project/static/
/wsgi/my_project/static/my_app/
/wsgi/my_project/my_app/static/
/wsgi/my_project/my_app/static/my_app/
Where should I place the static files, and have I configured it correctly?
I discovered that my_app was not in the INSTALLED_APPS list (apparently this is not part of the code structure I got from django-example). When I added the app to the list, it worked. The correct location of the static files: /wsgi/my_project/my_app/static/my_app/

Managing static files for multiple apps in Django

I am developing a Django (1.3) project composed of many applications. Each application has its own static files under its own static directory. Moreover, I have added a directory called project_static which should contain static files which are common throughout the various applications, such as jQuery.
The problem I immediately run into is that of naming collisions. By default, collectstatic will just put everything under a global static directory, without classifying them by application. This does not work for me, as each application has - for instance - a file called css/screen.css.
The way I solved it is by removing django.contrib.staticfiles.finders.AppDirectoriesFinder from STATICFILES_FINDERS and using namespaced static files dirs, so my settings now look like:
STATICFILES_DIRS = (
os.path.join(PROJECT_PATH, 'project_static'),
('my_app', os.path.join(PROJECT_PATH, 'my_app', 'static')),
('another_app', os.path.join(PROJECT_PATH, 'another_app', 'static')),
...
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
)
The problem is that in this way I lose the static files for all other applications (e.g. django.contrib.admin). Of course I could manually add the admin, but I'm not sure how to do this without breaking the admin, which has a different directory structure.
Is there a better way to manage the static files with more than one application?
This is the same problem that occurs with using app-specific templates directories. If you just throw the files directly under templates in the app, you'll end up with name collisions if two apps or even the project-level templates directory utilize templates of the same name. The fix for that is to actually put the templates in a directory of the name of app inside the templates directory like:
- some_app
- templates
- some_app
- index.html
So, I apply the same idea to static:
- some_app
- static
- some_app
- css
- img
- js
That way, when you run collectstatic, each individual app's static files get placed inside a namespaced directory. The only change you need to make is to prefix each of the files with the app-name directory in your templates. So instead of {{ STATIC_URL }}css/style.css you have {{ STATIC_URL }}my_app/css/style.css.