django-constance/docs/index.rst
Yurchenko Sergey 8f20ca3111 command-to-delete-stale-records (#355)
* command-to-delete-stale-records
2020-01-27 14:24:32 -05:00

411 lines
11 KiB
ReStructuredText

Constance - Dynamic Django settings
===================================
Features
--------
* Easily migrate your static settings to dynamic settings.
* Admin interface to edit the dynamic settings.
.. image:: screenshot2.png
Installation
------------
Install from PyPI the backend specific variant of django-constance:
For the (default) Redis backend::
pip install "django-constance[redis]"
For the database backend::
pip install "django-constance[database]"
Alternatively -- if you're sure that the dependencies are already
installed -- you can also run::
pip install django-constance
Configuration
-------------
Modify your ``settings.py``. Add ``'constance'`` to your
:setting:`INSTALLED_APPS`, and move each key you want to turn dynamic into
the :setting:`CONSTANCE_CONFIG` section, like this:
.. code-block:: python
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.staticfiles',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
...
'constance',
)
CONSTANCE_CONFIG = {
'THE_ANSWER': (42, 'Answer to the Ultimate Question of Life, '
'The Universe, and Everything'),
}
.. note:: Add constance *before* your project apps.
.. note:: If you use admin extensions like `Grapelli <http://grappelliproject.com/>`_, ``'constance'`` should be added in :setting:`INSTALLED_APPS` *before* that extension
Here, ``42`` is the default value for the key ``THE_ANSWER`` if it is
not found in the backend. The other member of the tuple is a help text the
admin will show.
See the :ref:`Backends <backends>` section how to setup the backend and
finish the configuration.
``django-constance``'s hashes generated in different instances of the same
application may differ, preventing data from being saved.
Use this option in order to skip hash verification.
.. code-block:: python
CONSTANCE_IGNORE_ADMIN_VERSION_CHECK = True
Signals
-------
Each time a value is changed it will trigger a ``config_updated`` signal.
You can use it as:
.. code-block:: python
from constance.signals import config_updated
@receiver(config_updated)
def constance_updated(sender, key, old_value, new_value, **kwargs):
print(sender, key, old_value, new_value)
The sender is the ``config`` object, and the ``key`` and ``new_value``
are the ones just changed.
This callback will get the ``config`` object as the first parameter so you
can have an isolated function where you can access the ``config`` object
without dealing with additional imports.
Custom fields
-------------
You can set the field type with the third value in the ``CONSTANCE_CONFIG`` tuple.
The value can be one of the supported types or a string matching a key in your :setting:``CONSTANCE_ADDITIONAL_FIELDS``
The supported types are:
* ``bool``
* ``int``
* ``float``
* ``Decimal``
* ``str``
* ``datetime``
* ``date``
* ``time``
For example, to force a value to be handled as a string:
.. code-block:: python
'THE_ANSWER': (42, 'Answer to the Ultimate Question of Life, '
'The Universe, and Everything', str),
Custom field types are supported using the dictionary :setting:``CONSTANCE_ADDITIONAL_FIELDS``.
This is a mapping between a field label and a sequence (list or tuple). The first item in the sequence is the string
path of a field class, and the (optional) second item is a dictionary used to configure the field.
The ``widget`` and ``widget_kwargs`` keys in the field config dictionary can be used to configure the widget used in admin,
the other values will be passed as kwargs to the field's ``__init__()``
Note: Use later evaluated strings instead of direct classes for the field and widget classes:
.. code-block:: python
CONSTANCE_ADDITIONAL_FIELDS = {
'yes_no_null_select': ['django.forms.fields.ChoiceField', {
'widget': 'django.forms.Select',
'choices': ((None, "-----"), ("yes", "Yes"), ("no", "No"))
}],
}
CONSTANCE_CONFIG = {
'MY_SELECT_KEY': ('yes', 'select yes or no', 'yes_no_null_select'),
}
If you want to work with files you can use this configuration:
.. code-block:: python
CONSTANCE_ADDITIONAL_FIELDS = {
'image_field': ['django.forms.ImageField', {}]
}
CONSTANCE_CONFIG = {
'LOGO_IMAGE': ('default.png', 'Company logo', 'image_field'),
}
When used in a template you probably need to use:
.. code-block:: html
{% load static %}
{% get_media_prefix as MEDIA_URL %}
<img src="{{ MEDIA_URL }}{{ constance.LOGO_IMAGE }}">
Images are uploaded to MEDIA_ROOT.
Ordered Fields in Django Admin
------------------------------
In order to Order the fields , you can use OrderedDict collection. Here is an example:
.. code-block:: python
from collections import OrderedDict
CONSTANCE_CONFIG = OrderedDict([
('SITE_NAME', ('My Title', 'Website title')),
('SITE_DESCRIPTION', ('', 'Website description')),
('THEME', ('light-blue', 'Website theme')),
])
Fieldsets
---------
To group settings together you can define fieldsets. Here's an example:
.. code-block:: python
CONSTANCE_CONFIG = {
'SITE_NAME': ('My Title', 'Website title'),
'SITE_DESCRIPTION': ('', 'Website description'),
'THEME': ('light-blue', 'Website theme'),
}
CONSTANCE_CONFIG_FIELDSETS = {
'General Options': ('SITE_NAME', 'SITE_DESCRIPTION'),
'Theme Options': ('THEME',),
}
.. note:: CONSTANCE_CONFIG_FIELDSETS must contain all fields from CONSTANCE_CONFIG
.. image:: screenshot3.png
Usage
-----
Constance can be used from your Python code and from your Django templates.
Python
^^^^^^
Accessing the config variables is as easy as importing the config
object and accessing the variables with attribute lookups::
from constance import config
# ...
if config.THE_ANSWER == 42:
answer_the_question()
Django templates
^^^^^^^^^^^^^^^^
To access the config object from your template you can either
pass the object to the template context:
.. code-block:: python
from django.shortcuts import render
from constance import config
def myview(request):
return render(request, 'my_template.html', {'config': config})
Or you can use the included config context processor. For Django pre-1.8, this looks like this:
.. code-block:: python
TEMPLATE_CONTEXT_PROCESSORS = (
# ...
'constance.context_processors.config',
)
For Django 1.8 and above, insert ``'constance.context_processors.config'`` at
the top of your ``TEMPLATES['OPTIONS']['context_processors']`` list. See the
`Django documentation`_ for details.
.. _`Django documentation`: https://docs.djangoproject.com/en/1.11/ref/templates/upgrading/#the-templates-settings
This will add the config instance to the context of any template
rendered with a ``RequestContext``.
Then, in your template you can refer to the config values just as
any other variable, e.g.:
.. code-block:: django
<h1>Welcome on {{ config.SITE_NAME }}</h1>
{% if config.BETA_LAUNCHED %}
Woohoo! Head over <a href="/sekrit/">here</a> to use the beta.
{% else %}
Sadly we haven't launched yet, click <a href="/newsletter/">here</a>
to signup for our newletter.
{% endif %}
Command Line
^^^^^^^^^^^^
Constance settings can be get/set on the command line with the manage command `constance`
Available options are:
list - output all values in a tab-separated format::
$ ./manage.py constance list
THE_ANSWER 42
SITE_NAME My Title
get KEY - output a single values::
$ ./manage.py constance get THE_ANSWER
42
set KEY VALUE - set a single value::
$ ./manage.py constance set SITE_NAME "Another Title"
If the value contains spaces it should be wrapped in quotes.
.. note:: Set values are validated as per in admin, an error will be raised if validation fails:
E.g., given this config as per the example app::
CONSTANCE_CONFIG = {
...
'DATE_ESTABLISHED': (date(1972, 11, 30), "the shop's first opening"),
}
Then setting an invalid date will fail as follow::
$ ./manage.py constance set DATE_ESTABLISHED '1999-12-00'
CommandError: Enter a valid date.
.. note:: If the admin fields is a `MultiValueField`, (e.g. datetime, which uses `SplitDateTimeField` by default)
then the separate field values need to be provided as separate arguments.
E.g., given this config::
CONSTANCE_CONFIG = {
'DATETIME_VALUE': (datetime(2010, 8, 23, 11, 29, 24), 'time of the first commit'),
}
Then this works (and the quotes are optional)::
./manage.py constance set DATETIME_VALUE '2011-09-24' '12:30:25'
This doesn't work::
./manage.py constance set DATETIME_VALUE '2011-09-24 12:30:25'
CommandError: Enter a list of values.
remove_stale_keys - delete all stale records in database::
$ ./manage.py constance remove_stale_keys
Record is considered stale if it exists in database but absent in config
Editing
-------
Fire up your ``admin`` and you should see a new app called ``Constance``
with ``THE_ANSWER`` in the ``Config`` pseudo model.
By default changing the settings via the admin is only allowed for super users.
But in case you want to use the admin's ability to implement custom
authorization checks, feel free to set the :setting:`CONSTANCE_SUPERUSER_ONLY`
setting to ``False`` and give the users or user groups access to the
``constance.change_config`` permission.
.. figure:: screenshot1.png
The virtual application ``Constance`` among your regular applications.
Custom settings form
--------------------
If you aim at creating a custom settings form this is possible in the following
way: You can inherit from ``ConstanceAdmin`` and set the ``form`` property on
your custom admin to use your custom form. This allows you to define your own
formsets and layouts, similar to defining a custom form on a standard
Django ModelAdmin. This way you can fully style your settings form and group
settings the way you like.
.. code-block:: python
from constance.admin import ConstanceAdmin, ConstanceForm, Config
class CustomConfigForm(ConstanceForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
#... do stuff to make your settings form nice ...
class ConfigAdmin(ConstanceAdmin):
change_list_form = CustomConfigForm
change_list_template = 'admin/config/settings.html'
admin.site.unregister([Config])
admin.site.register([Config], ConfigAdmin)
You can also override the ``get_changelist_form`` method which is called in
``changelist_view`` to get the actual form used to change the settings. This
allows you to pick a different form according to the user that makes the
request. For example:
.. code-block:: python
class SuperuserForm(ConstanceForm):
# Do some stuff here
class MyConstanceAdmin(ConstanceAdmin):
def get_changelist_form(self, request):
if request.user.is_superuser:
return SuperuserForm:
else:
return super().get_changelist_form(request)
Note that the default method returns ``self.change_list_form``.
More documentation
------------------
.. toctree::
:maxdepth: 2
backends
testing
changes
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`