Modifying your local settings.py

Every Lino site is defined by a Django settings module, usually defined in a file named settings.py.

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 the 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. The SITE setting is what turns a Django project into a Lino site.

As a site maintainer you can override many settings by modifying the settings.py file generated by getlino startsite.

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.

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

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 ('ledger', '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 file default.db in your project directory. On a production server you are of course going to set your own DATABASES, but this default value is the best choice for beginners.

  • USE_L10N and LANGUAGE_CODE (see lino.core.site.Site.languages for details on these)

  • LOGGING : See lino.utils.log.configure().

  • The ROOT_URL setting and the files urls.py and polls/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 a SITE variable and thus is designed to be used directly as a DJANGO_SETTINGS_MODULE.

Site-wide default settings

A Lino server configured using getlino 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 attribute 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 chose one of these languages in their preferences.

The site maintainer can change the language distribution with the Site.language attribute in the settings.py file.

language distribution

The list of languages that are activated on a given Lino site.

language code

A code that identifies a language for which screen messages have been translated.

Lino uses the same language codes as Django. 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 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.

Some common site settings

class lino.core.site.Site
languages = None

The language distribution to be used on this site.

This must be either None, or an iterable of language codes, or a string containing a space-separated series of language codes.

Examples:

languages = "en de fr nl et"
languages = ['en', 'fr']
languages = 'en'

The first language in this list is the site’s default language, returned by get_default_language().

use_help = False

Whether this site uses lino.modlib.help.

use_ipdict = False

Whether this site uses lino.modlib.ipdict.

Note that lino.modlib.ipdict unlike normal plugins should not be installed by adding it to your get_installed_apps() method but by setting this attribute. This approach has the advantage of also setting MIDDLEWARE_CLASSES automatically.

default_ui = 'lino.modlib.extjs'

The full Python name of the plugin that acts as main front end on this site.

Default value is lino.modlib.extjs. Other candidates are lino_react.react, lino.modlib.bootstrap3, lino_openui5.openui5, lino_xl.lib.pages and lino_extjs6.extjs6 .

Another possibility is to set it to None. In that case you must probably also set root_urlconf to a custom URL dispatcher.

Advanced site settings

class lino.core.site.Site
hidden_languages = None

A string with a space-separated list of language codes that should be hidden. This is useful when you have multilingual database content and a language distribution of more than three languages.

webdav_protocol

Set this to a string like e.g. ‘wdav’ to instruct Lino to use this custom protocol instead of http when linking to “editable” printable documents.

See WebDAV.

webdav_url

The URL location for webdav files. In a normal production configuration you should leave this unchanged and Lino will set the default value '/media/webdav/'. You also need to configure your web server to actually serve the files below this location using the WebDAV protocol. See WebDAV.

Obsolete: This may be used to simulate a WebDAV location on a development server. For example on a Windows machine, you may set it to w:\, and before invoking runserver, you issue in a command prompt:

subst w: <dev_project_path>\media\webdav
webdav_root

The path on server to store webdav files. Default is cache_dir + ´/media/webdav’.

custom_layouts_module

The name of the custom layouts module to be used on this site. Default value is defined by the application developer.

workflows_module

The name of the workflows module to be used on this site. Default value is defined by the application developer.

user_types_module

The name of the user types module to be used on this site. Default value is defined by the application developer.

For example:

class Site(Site):
    user_types_module = 'myapp.user_types'
use_security_features = False

Set this to True in order to activate a selection of security features to protect against miscellaneous attacks. You can do this only if your application is being served via HTTPS. The idea is to provide a reasonable security out of the box.

This will activate some middleware and set some security-related settings. This is a new feature and not much tested. As a hoster you may prefer adding security manually using your established standards (regarding security Lino does not add anything to plain Django). See also Security of Lino applications.

root_urlconf = 'lino.core.urls'

The value to be assigned to ROOT_URLCONF when this Site instantiates.

The default value is lino.core.urls.

social_auth_backends = None

A list of backends for Python Social Auth (PSA).

Having this at a value different from None means that this site uses authentication via third-party providers.

Sites which use this feature must also install PSA into their environment (which is done automatically by install).

Depending on the backend you must also add credentials in your local settings.py file, e.g.:

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = \
  '1234567890-a1b2c3d4e5.apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'SH6da...'

A working example is in the lino_book.projects.noi1e demo project.

appy_params = dict(
ooPort=8100, pythonWithUnoPath='/usr/bin/python3',
raiseOnError=True)

Used by lino_xl.lib.appypod.choicelist.AppyBuildMethod.

Allowed keyword arguments for appy.pod.renderer.Render are:

pythonWithUnoPath=None,
ooPort=2002
stylesMapping={}
forceOoCall=False,
finalizeFunction=None
overwriteExisting=False
raiseOnError=False
imageResolver=None

See the source code for details.

See also Running a LibreOffice server

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.

See https://docs.djangoproject.com/en/3.1/topics/settings/

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.