.. _startup: ================================= When a Lino application starts up ================================= This chapter describes what happens during :term:`site startup`. .. glossary:: site startup The things that happen at the beginning of a Lino process. Lino process A Python process on a given :term:`Lino site`. This is either some :term:`django-admin command`, or a WSGI process inside a web server. There are four major phases in the life of a :term:`Lino process`: .. glossary:: application definition The first part of the :term:`site startup` when Django **settings** are being loaded. We see this as a separate phase because Lino does some magics there. data definition The second part of the :term:`site startup` when Django **models** are being loaded. site analysis The third part of the :term:`site startup` when Django models are loaded, and Lino analyzes them to add its own data structures. runtime When the :term:`site startup` has finished and the actual process does what it is designed to do. There are three :mod:`lino.api` modules named after these phases: - :mod:`lino.api.ad` is available during :term:`application definition`. - :mod:`lino.api.dd` is available during :term:`data definition` and :term:`site analysis`. - :mod:`lino.api.rt` is available when :term:`site analysis` has finised. A more detailed description follows. - The :xfile:`manage.py` script causes the module specified by :envvar:`DJANGO_SETTINGS_MODULE` (your :xfile:`settings.py` module) to be imported. This might happen twice (e.g. with :manage:`runserver`). Everything in :mod:`lino.api.ad` is usable. - Importing the :xfile:`settings.py` module will instantiate your :setting:`SITE`. - When settings are ready, Django will load the :xfile:`models.py` modules. Everything in :mod:`lino.api.dd` is usable during this step. :mod:`lino.api.rt` may be imported but should not be accessed at global module level. - When all :xfile:`models.py` modules are loaded, the Site will "start up". - Only now everything in :mod:`lino.api.rt` is usable. The Site startup phase ====================== .. currentmodule:: lino.core.site - Emit the :data:`lino.core.signals.pre_startup` signal - Run :meth:`lino.core.plugins.Plugin.on_site_startup` on each plugin - Instantiate the kernel. :attr:`settings.SITE.kernel ` is now an instance of :class:`lino.core.kernel.Kernel` instead of `None`. - Import :attr:`Site.user_types_module` - Run :attr:`Site.do_site_startup`, which does the following: - Emit the :data:`lino.core.signals.pre_analyze` signal - Import :attr:`Site.custom_layouts_module` - Call :meth:`lino.core.model.Model.on_analyze` on every model. - Discover and initialize actors - Emit the :data:`lino.core.signals.post_analyze` signal - Run :meth:`lino.core.actors.Actor.after_site_setup` on each actor - Emit the :data:`lino.core.signals.pre_ui_build` signal - Run :meth:`lino.core.plugins.Plugin.on_ui_init` on each plugin - Run :meth:`lino.core.plugins.Plugin.post_site_startup` on each plugin - Emit the :data:`lino.core.signals.post_startup` signal A server startup signal for Django ================================== **This section is obsolete.** It was for Django before 1.7. Lino provides a solution for Django's old problem of not having an "application server startup signal", a signal to be emitted when the models cache has been populated. About the problem ----------------- The problem is old: - In March 2010, wojteks suggested to call it "server_initialized" in his :djangoticket:`13024` ("Signal sent on application startup"). This ticket has been closed because it was "fixed in a branch which needs review. See #3591." - :djangoticket:`3591` ("add support for custom app_label and verbose_name") seems truly very interesting and truly very complex, but didn't get into 1.5. Obviously it's not easy to find a good solution. Note that this is *not* the same problem as in `Entry point hook for Django projects `__ (2013-02-14) where Brian Rosner describes a method for "running code when Django starts". We don't want to run code *when* Django starts, but *after* Django has finished to start. The difference is important e.g. if you want to analyze all installed models. How Lino solves it ------------------ The basic trick is to simply send the signal "at the end of your last app's models.py file" as described by `Ross McFarland on Sun 24 June 2012 `_. That's why :mod:`lino` must be the *last* item of your :setting:`INSTALLED_APPS`. .. currentmodule:: lino.core.site Although :mod:`lino` doesn't have any model of its own, it does have a `models` module which invokes the :meth:`startup ` method. The :meth:`startup ` method then emits a :attr:`startup ` signal. Result is that you can now write code like the following in any `models` or `admin` module of your existing project:: from djangosite.signals import startup, receiver @receiver(startup) def my_handler(sender,**kw): # code to run exactly once per process at startup print sender.welcome_text()