2021-01-07 16:48:14 -06:00
|
|
|
|
|
|
|
.. highlight:: ini
|
|
|
|
|
|
|
|
Storing Config in DB
|
|
|
|
====================
|
|
|
|
|
|
|
|
We're getting ahead of ourselves a little here, if you're reading this manual
|
|
|
|
straight through. But for reference sake this probably belongs here.
|
|
|
|
|
|
|
|
Settings Table
|
|
|
|
--------------
|
|
|
|
|
|
|
|
If you already have a Rattail DB, then it has a table named ``setting`` which
|
|
|
|
is designed to store config values. It's just a regular table so you can write
|
|
|
|
settings via SQL if you like:
|
|
|
|
|
|
|
|
.. code-block:: sql
|
|
|
|
|
|
|
|
insert into setting (name, value) values ('rattail.app_title', 'Poser');
|
|
|
|
|
|
|
|
update setting set value = 'Something Else' where name = 'rattail.app_title';
|
|
|
|
|
|
|
|
Although the main reason for putting settings in the DB is usually so you can
|
|
|
|
edit them via the web app.
|
|
|
|
|
|
|
|
|
|
|
|
Telling App to Read Config from DB
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
Well first of all we must assume that the DB connection itself is configured.
|
|
|
|
More on that later but let's say you have this in place::
|
|
|
|
|
|
|
|
[rattail.db]
|
|
|
|
default.url = postgresql://user:password@localhost/poser
|
|
|
|
|
|
|
|
Then you also must tell the Rattail config engine that a) it should read config
|
|
|
|
values from the DB at all, but probably also b) it should *prefer* values from
|
|
|
|
the DB over what was read from file. Do this within your config file::
|
|
|
|
|
|
|
|
[rattail.config]
|
|
|
|
usedb = true
|
|
|
|
preferdb = true
|
|
|
|
|
|
|
|
With this in place, when the app requests a config value, it will come from the
|
|
|
|
DB if present, falling back to the file value if that exists.
|
|
|
|
|
|
|
|
|
|
|
|
File vs. DB Setting Names
|
|
|
|
-------------------------
|
|
|
|
|
2022-08-08 15:31:28 -05:00
|
|
|
You may have noticed that the SQL examples above, and the examples
|
|
|
|
used in :doc:`syntax` are really for the same ``app_title`` setting,
|
|
|
|
but there is a key difference in naming.
|
2021-01-07 16:48:14 -06:00
|
|
|
|
|
|
|
So in a config file you might have this snippet to define a setting::
|
|
|
|
|
|
|
|
[rattail]
|
|
|
|
app_title = Poser
|
|
|
|
|
|
|
|
But then that same setting is written in SQL as:
|
|
|
|
|
|
|
|
.. code-block:: sql
|
|
|
|
|
|
|
|
insert into setting (name, value) values ('rattail.app_title', 'Poser');
|
|
|
|
|
|
|
|
In other words the "section" and "option" names from the config file, are
|
|
|
|
joined together with a dot, for the DB setting name.
|
|
|
|
|
|
|
|
When the app requests a config value, it must specify both a section and
|
|
|
|
option. The config engine then will auto-join them as needed when doing DB
|
|
|
|
lookups.
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
config.get('rattail', 'app_title')
|
|
|
|
|
|
|
|
|
|
|
|
Avoiding the DB
|
|
|
|
---------------
|
|
|
|
|
|
|
|
The app can request config from "file only" if it needs to. It just has to
|
|
|
|
specify a flag when reading the value, for example:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
config.get('rattail', 'app_title', usedb=False)
|
2022-08-08 15:31:28 -05:00
|
|
|
|
|
|
|
|
|
|
|
DB Settings Cache
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
One downside of reading config values from the DB settings table, is
|
|
|
|
the number of queries involved, as each call to ``config.get()`` would
|
|
|
|
normally involve a separate SQL query. (Not only that, but unless a
|
|
|
|
DB session is passed to ``config.get()`` a new one will be made just
|
|
|
|
for the query.)
|
|
|
|
|
|
|
|
To help with this, you can enable caching for the DB settings. This
|
|
|
|
should "just work" as expected; i.e. calls to ``config.get()`` need
|
|
|
|
not change. (Although there's no point in passing a DB session when
|
|
|
|
caching is enabled.)
|
|
|
|
|
|
|
|
To turn on the caching, add to your config file::
|
|
|
|
|
|
|
|
[rattail.config]
|
|
|
|
beaker_cache.enabled = true
|
|
|
|
|
|
|
|
By default this cache will be file-based, storage for which is at
|
|
|
|
e.g. ``/srv/envs/poser/app/cache/config/`` although you can override
|
|
|
|
the paths if you prefer::
|
|
|
|
|
|
|
|
[rattail.config]
|
|
|
|
beaker_cache.enabled = true
|
|
|
|
beaker_cache.data_dir = /somewhere/else/data
|
|
|
|
beaker_cache.lock_dir = /somewhere/else/lock
|
|
|
|
|
|
|
|
memcached
|
|
|
|
=========
|
|
|
|
|
|
|
|
If you're not crazy about caching to disk and would prefer to use
|
|
|
|
`memcached`_ as the backend instead, first install that:
|
|
|
|
|
|
|
|
.. _memcached: https://www.memcached.org/
|
|
|
|
|
|
|
|
.. code-block:: sh
|
|
|
|
|
|
|
|
sudo apt install memcached
|
|
|
|
|
|
|
|
Then install the Python dependencies to your virtual environment:
|
|
|
|
|
|
|
|
.. code-block:: sh
|
|
|
|
|
|
|
|
cd /srv/envs/poser
|
|
|
|
source bin/activate
|
|
|
|
pip install 'rattail[memcached]'
|
|
|
|
|
|
|
|
And finally add to your config file::
|
|
|
|
|
|
|
|
[rattail.config]
|
|
|
|
beaker_cache.enabled = true
|
|
|
|
beaker_cache.type = ext:memcached
|
|
|
|
beaker_cache.url = 127.0.0.1:11211
|
|
|
|
|
|
|
|
Rattail will try to come up with a unique namespace to use for the
|
|
|
|
cache; this is needed in situations where the same ``memcached``
|
|
|
|
service is handling multiple "separate" Rattail apps. You can also
|
|
|
|
explicitly set the namespace to use, e.g.::
|
|
|
|
|
|
|
|
[rattail.config]
|
|
|
|
beaker_cache.namespace = my_custom_namespace
|