Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
Dynamic models¶
This document collects ideas on one possible way for working around inject_field (#246)
General stuff:
>>> from lino import startup
>>> startup('lino_book.projects.min9.settings')
>>> from lino.api.doctest import *
BTW: The dynamic-models project confirms that it is possible.
First¶
We will add a new attribute dynamic_models
for
lino.core.plugin.Plugin
. This is a list or tuple of strings,
each string is of the form "<app_label>.<ModelName>"
and specifies
a model whose class object should get dynamically factored.
When the Site object instantiates (i.e. before Django sees the settings) it will collect the dynamic_models of all plugins and create dynamic class objects for each of them. These class objects inherit from all mixins found in all installed plugins.
With at least one gotcha: these mixins must get defined in a module
called bases.py
. That’s because we cannot import any
models.py
file before
Models that are candidates for dynamic factoring must use the is_abstract_model <lino.core.site.Site.is_abstract_model> method when declaring their inner Meta class. But then?
Second¶
system/__init__.py
:
class Plugin(ad.Plugin):
...
system/mixins.py
:
class SiteConfigBase(dd.Model):
class Meta:
abstract = True
verbose_name = _("Site configuration")
system/models.py
:
from .mixins import *
SiteConfig = dd.dynamic_model(SiteConfigBase)
other/__init__.py
:
class Plugin(ad.Plugin):
...
other/mixins.py
:
from lino.modlib.system.mixins import SiteConfigBase
class OtherSiteConfig(SiteConfigBase):
class Meta:
abstract = True
other/models.py
:
from .mixins import *
But how to implement dd.dynamic_model(SiteConfigBase)? The challenge is that Lino must discover all abstract models which inherit from the given class.
Abstract models are not stored in the models cache:
>>> from django.apps import apps
>>> [m for m in apps.get_models() if m._meta.abstract]
[]
And anyway the models cache is ready only when all models modules have been imported. Which means that it is not easy.