Is the order of apps in INSTALLED_APPS important? I ask it because I have settings folder with two settings files: base.py and production.py and I put all my settings in base.py and then in production.py, I have:
from base import *
and then I override some settings.
Also in my base.py, I make INSTALLED_APPS a list, not a tuple. Because I want to remove some apps for production settings.
In production.py I want to write:
NOT_USED_APPS = ['debut_toolbar', 'other_odd_app',]
INSTALLED_APPS = list(set(INSTALLED_APPS) - set(NOT_USED_APPS))
In this case, the order of apps in INSTALLED_APPS is not like in base.py
Yes, the order is quite important.
From Django official docs on INSTALLED_APPS settings:
When several applications provide different versions of the same
resource (template, static file, management command, translation), the
application listed first in INSTALLED_APPS has precedence.
Example-1 Templates:
django.template.loaders.app_directories.Loader
If this template loader is enabled in your DjangoTemplates backend in the TEMPLATES setting or if you have passed it as a loaders argument to Engine, then it loads templates from Django apps on the filesystem.
For each app in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django will look for templates in there.
Lets say in my project, i have defined INSTALLED_APPS as:
INSTALLED_APPS = ('myproject.app1', 'myproject.app2')
Now, i want to get the template some_template.html. Then get_template('some_template.html') will look for some_template.html in these directories, in this order:
/path/to/myproject/app1/templates/ # checks here first
/path/to/myproject/app2/templates/ # Then checks here
It will then use the one which it finds first.
Quoting from that section:
The order of INSTALLED_APPS is significant!
Example-2: Translations
Django applies the following algorithm for discovering translations:
The directories listed in LOCALE_PATHS have the highest precedence, with the ones appearing first having higher precedence than the ones appearing later.
Then, it looks for and uses if it exists a locale directory in each of the installed apps listed in INSTALLED_APPS. The ones appearing first have higher precedence than the ones appearing later.
Finally, the Django-provided base translation in django/conf/locale is used as a fallback.
We can see that order is important here also.
Example-3 Management Commands:
From Django 1.7 release notes on management commands and order of INSTALLED_APPS:
When several applications provide management commands with the same
name, Django loads the command from the application that comes first
in INSTALLED_APPS. Previous versions loaded the command from the
application that came last.
This brings discovery of management commands in line with other parts
of Django that rely on the order of INSTALLED_APPS, such as static
files, templates, and translations.
I experimented a bit and found two other things that I deemed useful to know:
The order in INSTALLED_APPS doesn't seem to effect when the models are created. Django figures out that certain models depend on others and run them in the correct order.
The apps ready method in the AppConfig object seems to run in the order they appear in INSTALLED_APPS.
Related
I've been trying for some time to override the edit.html template for a single BaseSiteSetting in wagtail.
I'm not sure if this is even possible. My overrides for ModelAdmin templates are working just fine by using the following directory structure:
ModelAdmin index.html override
Is the same possible for my setting? Which is located in my success_stories app models.
I've looked through the wagtail/contrib/settings/templates/wagtailsettings/edit.html file but it's unclear to me how to do this. I've always worked with headless wagtail and don't have a lot of experience with templates.
The wagtail docs only seem to mention ModelAdmin overrides.
This would be done via standard Django template overrides: The first template that matches wins the cake.
In your case the template for the Wagtail Settings contrib module is located under templates/wagtailsettings/edit.html which means that in your app's template directory you have to make the exact same setup:
<you_app_directory>/templates/wagtailsettings/edit.html
Then depending on how you have setup your template discovery and/or have setup your app loading order one of the above templates will match first. So in order for your template to be the first one to match you can do two things:
Alter the loading order of your apps and make sure that your app comes before the wagtail.contrib.settings in your INSTALLED_APPS Django settings listing:
INSTALLED_APPS = [
...
<your_app>,
wagtail.contrib.settings
...
]
Or you can alter how templates are discovered by Django by changing the TEMPLATES setting:
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / 'templates'],
"APP_DIRS": True,
...
},
]
Notice that DIRS comes before APP_DIRS, the order here matters as well. First Django will look in the directories you specify in DIRS, if nothing matched it will continue to look in the installed application directories.
Note that with the latter method BASE_DIR / 'templates' is a single templates directory at the root of your project.
Usually, if overriding third-party templates, the first method is used.
The tutorial on the site creates an app named polls. It's using django 1.9, so in the INSTALLED_APPS it is:
polls.apps.PollsConfig
I'm watching a tutorial he names the app newsletter and in INSTALLED_APPS he has
newsletter
he's using 1.8, though. I am using 1.9. I've watched other tutorials and they also just add a name without dots in the syntax as he does. I realize things may be different, that's understood. To be clear if I named my app dogs,. in the installed apps it would be named like this
dogs.apps.DogsConfig
or if it was tree it would be
tree.apps.TreeConfig
Is that how the naming convention goes? also I would assume things would get shorter in newer versions and more convenient. so to go from just adding
newsletter,
to having to type out
polls.apps.PollsConfig
seems weird to me. But I'm new so I maybe missing something. Any and all advice is welcome
That is the Application Configuration feature, new to Django 1.7.
Basically, now you can list in INSTALLED_APPS either the module that contains the application or a class that derives from django.apps.AppConfig and defines the behavior of the application.
This feature provides several advantages:
Apps can be configured more easily, and even subclassed for customization.
You can have several apps in the same module.
Application modules can define the special module variable default_app_config to specify the name of their AppConfig, so that they can use the new features without having to specify the full name of that class in INSTALLED_APPS. But this is a backwards compatibility feature and new applications are recommended to write the full AppConfig name.
Anyway, most django/contrib apps use that default_app_config, for compatibility with old configurations. See for example the file django/contrib/messages/__init__.py is just:
from django.contrib.messages.api import *
from django.contrib.messages.constants import *
default_app_config = 'django.contrib.messages.apps.MessagesConfig'
So, adding it up, per OP request:
If you add in INSTALLED_APPS the typename foo.apps.FooConfig, then that class will be used to setup the foo app, 1.7 style (recommended).
If you add in INSTALLED_APPS the plain name foo, then:
if there is a variable foo.default_app_config this class will be used to setup the foo app, 1.7 style. Most (all?) the standard Django apps have this variable, so that you don't need to change your INSTALLED_APPS when you upgrade from Django-1.6 to Django-1.7.
if there is not such a variable, then the 1.6 style application will be used, with default values for the advanced configuration options.
In the setup.py ,under the Installed apps just add app_name like
INSTALLED_APPS = [
'polls', # <--- here
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
While I was searching about INSTALLED_APPS constant like you I have seen this explanation on documents:
A list of strings designating all applications that are enabled in this Django installation. Each string should be a dotted Python path to:
an application configuration class (preferred), or
a package containing an application.
The second bullet is explaining that you can use your application folder for resolving the existing settings automatically. The first option can be also used for activate your application. But the most important thing is that it is preferred one.
If you want to go with the preferred one first you have to create app.py in your new application folder then set like this:
# my_new_app/apps.py
from django.apps import AppConfig
class MyNewAppConfig(AppConfig):
name = 'my_new_app'
verbose_name = "My Brand New Application"
# my_new_app/__init__.py
default_app_config = 'my_new_app.apps.MyNewAppConfig'
Why the first one is preferred? Because I think of that it is explicit.
I use django and my application works, when I change the style.css the app changes etc.
However, I recently found out that I didn't define STATICFILES_DIR, I only defined
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
Which is only for collectstatic.
But now I'm wondering, how does django know where to look for the static files?
Specifically in the polls/static/polls directory?
Django will look for a directory named static in each of your apps by default. More on this later.
From the documentation:
Now we might be able to get away with putting our static files
directly in my_app/static/ (rather than creating another my_app
subdirectory), but it would actually be a bad idea. Django will use
the first static file it finds whose name matches, and if you had a
static file with the same name in a different application, Django
would be unable to distinguish between them.
The key part being
...Django will use the first static file it finds whose name matches...
There are Django libraries called "static file finders" that help with this process. You can configure them by modifying the installed apps in your Django configuration file.
According to the documentation, they're actually undocumented, because they are considered private. However, you can look at the source code for those "finders" on GitHub.
Django projects are composed of modules called apps. Each app contains some default files when you generate it. Although there is configuration, there's plenty of convention about Django too. For example, the views.py file. Another such convention is your app's static directories folder.
Your STATICFILES_DIR array allows you to add additional places for you to put your static files. This is useful, as you'll see when you prepare to deploy, because of the way Django handles static files in a real-world environment.
It's totally optional, but it's there to make your life easier later.
I have a web application with an associated API and database.
I'd like to use the same Django models in the API, but have it served separately by different processes so I can scale it independently.
I also don't need the API to serve static assets, or any of the other views.
The complication is that the routes I have defined have the API and the webapp sharing the root domain:
http://domain.com/normal/application/stuff
http://domain.com/api/different/stuff
and additionally my Django apps depend on each other's models and constants (so two different settings.py files with different INSTALLED_APPS doesn't quite solve it).
I guess one way is I could define different processes in my Procfile which just start the Django app, but that in one of the processes it might have different environment variables? I don't think I can change the environment per Proc with heroku:config, I think it would actually have to be a directive in the Procfile.
Anyone have any experience or insight with this? Thanks!
As Daniel said you could just use two settings files, with a shared base. If you want to serve a subset of the urls you should just also create separate url definitions in the ROOT_URLCONF setting.
So your project structure would be something like this:
project/
project/
settings/
__init__.py
base.py
normal.py
api.py
urls/
__init__.py
base.py
normal.py
api.py
wsgi/
__init__.py
normal.py
api.py
settings/normal.py (analog for api) would be somthing like this:
from .base import *
ROOT_URLCONF = 'project.urls.normal
I don't think you need different environment variables, just a separate WSGI file pointing to a different settings.py. Those settings file can import shared settings from a common file, then set their particular values for INSTALLED_APPS. Then the Procfile can refer to those wsgi files in separate processes.
I'm making a very very reusable CMS in Django. I'm trying not to hardcode anything, so I want a config.py or something for the app itself.
I want to use it in templates (something like {{ config.SITE_NAME }}) and just regular Python code (views, models), etc.
How would I go about doing that?
Django already has the settings.py file and an interface to use the values from there, is that not good enough? Accessing settings in your code is easy:
from django.conf import settings
do_something_with(settings.MY_CONFIG_VARIABLE)
In your template it requires a bit more work, like making a context processor for example. This answer shows you have to make a context processor that exposes values from settings to your template.
settings.py serves this purpose already in django. You can add custom settings to it for your application.
https://docs.djangoproject.com/en/dev/topics/settings/#using-settings-in-python-code
When you create a django project, it automatically creates a settings.py file. Put your settings in that file, and then :-
from django.conf import settings
settings.YOUR_SETTING
also, if you have some settings, that will vary depending upon the machines (eg. production/test servers).
Then just add eg. conf/local_settings.py file and put the machine specific settings in that file, and in settings.py just do :-
from conf.local_settings import *
at the end of settings.py
Make sure you ignore local_settings.py from your VCS check-in (eg. in case of git add local_settings.py to .gitignore