Installation | Topics | Beyond Lino
The local settings.py
file¶
This document explains how to organize, edit and manage your local configuration options. For a list of the actual options, see Site settings reference for maintainers
Overview¶
Every Lino site is defined by a Django settings module, usually
defined in a file named settings.py
, which is generated by
getlino startsite
.
As a server administrator you are responsible for modifying the
settings.py
file. It is not meant for being editable by the site
operator (via the web interface) because a change might
require a database migration
have commercial consequences like a changed hosting price or a fee for modifying them.
This file contains configuration options that the site operator might want to discuss with their server administrator.
Types of configuration options¶
As a server administrator you should understand two types of options
you can configure in a settings.py
file.
- site setting¶
A configuration option that can be set for a given Lino site by its server administrator.
For example the
languages
setting:class Site(Site): languages = "en fr"
- plugin setting¶
A configuration option that is used only by a given plugin.
For example the
notify.remove_after
setting:def get_plugin_configs(self): yield super().get_plugin_configs() ... yield ('notify', 'remove_after', 24*7)
A configuration option that decides which plugins are to get installed cannot be
a plugin setting because it must be known when the Site
instantiates.
The name of a plugin setting contains a dot (.
) and is of format
app_label.attrname
while a site setting has a name without a dot.
Modifying your local settings.py
¶
To edit your local settings.py
file, go to the project directory and
start your preferred editor on it:
go mysite
nano settings.py
After modifying your settings.py
you must run
reload_services.sh
to restart all services that use Lino.
A minimal Lino settings.py
contains something like this:
from foo.bar.settings import *
SITE = Site(globals())
# more local settings here
That is, you import the default settings of some Lino application into
your local settings module, including a Site
class, then you
instantiate that Site
class and store this instance in a variable
named SITE
. Every Lino site requires a setting named
SITE
.
- SITE¶
The instance of
lino.core.site.Site
(or a subclass thereof) that defines the application that is running on this site. TheSITE
setting is what turns a Django project into a Lino site.
The settings.py
file must be valid Python syntax. One pitfall if you
have no experience with Python is that indentation is important. Also make
sure that your text editor doesn’t replace spaces by tabs.
In case of doubt, before restarting the server, you may issue the
following command to test whether your settings.py
is okay:
$ python manage.py validate
Editing the settings.py
can require a database change¶
Every change in a settings.py
file may potentially (but not
necessarily) require a change the database structure.
For example the database is likely to change when you modify the line “from foo.bar.settings import *” because that switches to another application. Every application has its own database structure.
Or if you change the languages
setting and your application uses
multilingual database content.
Or certain plugin settings influence the database, for example
accounting.has_payment_methods
.
Adapting the database to your changes in the settings.py
file is easy
when this is just a demo site: you simply run pm prep
and you’re
done. On a production site you basically make a database snapshot before
your change and restore that snapshot after the change (as for example in
Upgrading a production site).
Inheriting settings¶
You might be surprised to see the following construct:
from foo.bar.settings import *
class Site(Site):
title = "My title"
SITE = Site(globals())
We are just using a feature of the Python language that allows us to define a new class based on an existing class and having the same name as its parent.
A settings.py
file generated by getlino also adds the following:
def get_plugin_configs(self):
yield super(Site, self).get_plugin_configs()
# example of local plugin settings:
# yield ('accounting', 'start_year', 2018)
That is, you override the lino.core.site.Site.get_plugin_configs()
method.
Lino dynamically creates your Django settings¶
The first argument of the instantiator must be the global namespace of your settings module (globals()). Lino uses this to fill “intelligent default values” to your settings module’s global namespace.
In other words, Lino is going to automatically set certain Django
settings. Including for example INSTALLED_APPS
and
DATABASES
.
Note that Lino writes to your settings module’s global namespace only
while the Site class gets instantiated. So if for some reason you
want to modify one of the settings, do it after your
SITE=Site(globals())
line.
You’ve maybe heard that it is not allowed to modify Django’s settings
once it has started. But there’s nothing illegal with this here
because this happens before Django has seen your settings.py
.
Lino does more than this. It will for example read the __file__
attribute of this, to know where your settings.py
is in the
file system.
Here are some of the Django setting for which Lino sets default values:
DATABASES
: a SQLite database in a filedefault.db
in your project directory. On a production server you are of course going to set your ownDATABASES
, but this default value is the best choice for beginners.USE_L10N
andLANGUAGE_CODE
(seelino.core.site.Site.languages
for details on these)LOGGING
: Seelino.utils.log.configure()
.The
ROOT_URL
setting and the filesurls.py
andpolls/views.py
generated by Django are not necessary. With Lino you don’t need to worry about URLs and views because Lino defines them for you.
Lino’s settings.py
files are small¶
Lino helps you to keep settings.py
files small because it delegates the
responsibility of maintaining default values for Django settings to the
application developer.
A typical settings.py
file for a Lino site consists of a few lines
(plus, on a production site, the lines for defining your DATABASES
setting). Compare this to a settings.py
file generated by Django’s
startproject
command which contains 120 lines of text (Django version
2.2.7).
>>> from atelier.sheller import Sheller
>>> shell = Sheller() # will run in a temporary directory
>>> shell("django-admin startproject foo")
>>> shell("wc -l foo/foo/settings.py")
120 foo/foo/settings.py
>>> shell("django-admin --version")
3.1.7
The Django settings module¶
The Django settings module is the most important thing in Django. Almost everything you do with Django requires the settings module to be loaded. Django does that automagically as soon as a Python process accesses the settings. And when that moment arrives, Django needs to know the name of your settings module.
You can specify this name either using the DJANGO_SETTINGS_MODULE
environment variable or the –settings command-line option of most
django-admin commands.
To illustrate what happens when Django doesn’t know the settings module, let’s
open a Python session in an environment with Django installed but without any
DJANGO_SETTINGS_MODULE
environment variable defined, and then type:
>>> from django.conf import settings
This will pass. We said almost everything requires the settings to be loaded.
You may import the django.conf.settings
module. But as soon as you want
to actually access some attribute of this module, you will get an
ImproperlyConfigured exception:
>>> print(settings.DEBUG)
Traceback (most recent call last):
...
django.core.exceptions.ImproperlyConfigured: Requested setting DEBUG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
A Django settings module must be importable. That is, if
DJANGO_SETTINGS_MODULE
contains e.g. foo.bar.baz
, then
Django will do the equivalent of import foo.bar.baz
.
Settings packages¶
We use to speak about “the settings.py
file”, but in reality the
Django settings module can be in some arbitrary filename. Some Django
sites use a layout called a settings package, which is
useful when you want to have different variants of settings modules.
In some projects we use a whole package of settings:
settings/__init.py
: the base for all modules of this package.settings/demo.py
: instantiates aSITE
variable and thus is designed to be used directly as aDJANGO_SETTINGS_MODULE
.
Site-wide default settings¶
A Lino server configured using getlino : the Lino installer can provide a module with
server-wide default settings for this server, and individual sites can decide to
import these. Such a module (despite the fact that it is also in a file named
settings.py
) is not a Django settings module.
Here are some typical Django settings for which a server-wide default value
makes sense: ADMINS
EMAIL_HOST
SERVER_EMAIL
DEFAULT_FROM_EMAIL
STATIC_ROOT
TIME_ZONE
Multilingual Lino sites¶
The languages
setting in the settings.py
file of a
Lino site specifies what we call the language distribution.
The language distribution controls two things: (1) the front end languages available on this site and (2) how multilingual database content is stored in your database.
Every site user may choose one of these languages in their user settings.
The server administrator can change the language distribution by specifying
the languages
setting in the settings.py
file.
Lino uses the same language codes as Django.
- language code¶
A code that identifies a language for which screen messages have been translated.
You can see the list of available languages in django/conf/global_settings.py.
You may use any of these languages, but Lino-specific messages are currently being translated only into German, French, Estonian and Dutch. You are welcome to contribute translations to your language of choice. See https://www.lino-framework.org/dev/translate
Having more than one language in your language distribution will make your Lino site multilingual. Changing this setting may change your database structure and thus might require a data migration. This is because this setting also controls how multilingual database content is stored in your database.
Two possibilities to override site attributes¶
There are two possibilities to override the Site
attributes. The most
basic way is:
from lino_noi.lib.noi.settings import *
SITE = Site(globals(), title="My Lino site", is_demo_site=False, languages="en fr")
DEBUG = True
The more explicit way is this:
from lino_book.projects.chatter.settings import *
class Site(Site):
title = "My Lino site"
is_demo_site = False
languages = "en fr"
SITE = Site(globals())
DEBUG = True
This way is recommended because it allows to override methods as well. Yes,
Lino saves us not only from having to define all-uppercase settings, it also
adds the full power of the Python language to your settings.py
file.
Summary¶
- Django settings module¶
A module that is imported by a Python process when it uses Django. It is just a Python module with module-level variables, most of them upper-case. It is usually stored in a file named
settings.py
.
- DJANGO_SETTINGS_MODULE¶
The environment variable that is expected to contain the Python name of the Django settings module.
- settings.py¶
The conventional name of a file that contains a Django settings module.
Note that a file of this name also can contain Site-wide default settings or the default
Site
class of a Lino application.
Don’t read¶
A site feature is a deprecated term. The concept no longer exists.
- site feature¶
Was used to designate a boolean configuration option that can be either enabled or disabled for a given Lino site by its server administrator. It can influence the list of installed plugins.
For example the
third_party_authentication
setting:SITE.activate_feature("third_party_authentication")