diff --git a/docs/cookbook.rst b/docs/cookbook.rst index 7ab5637..c86782f 100644 --- a/docs/cookbook.rst +++ b/docs/cookbook.rst @@ -8,8 +8,8 @@ Calling a Django management command If you want to call a Django management command programmatically, say from a script outside of your usual Django code, you can use the -equivalent of Django's :func:`~django.core.management.call_command` function -with django-configurations, too. +equivalent of Django's :func:`~django.core.management.call_command` +function with django-configurations, too. Simply import it from ``configurations.management`` instead: @@ -31,17 +31,17 @@ the ``DOTENV`` setting to the appropriate file name: # mysite/settings.py - from os.path import dirname, join + import os.path from configurations import Configuration - BASE_DIR = dirname(dirname(__file__)) + BASE_DIR = os.path.dirname(os.path.dirname(__file__)) class Dev(Configuration): - DOTENV = join(BASE_PATH, '.env') + DOTENV = os.path.join(BASE_DIR, '.env') SECRET_KEY = values.SecretValue() -An ``.env`` file is an ``.ini``-style file. It must contain a list of +A ``.env`` file is a ``.ini``-style file. It must contain a list of ``KEY=value`` pairs, just like Shell environment variables: .. code-block:: ini @@ -93,6 +93,42 @@ Python instead of from the command line. .. _envdir: https://pypi.python.org/pypi/envdir +Sentry (dynamic setup calls) +---------------------------- + +For all tools that require an initialization call you should use +:ref:`Setup methods` (unless you want them activated +for all environments). + +Intuitively you might want to add the required setup call like any +other setting: + +.. code-block:: python + + class Prod(Base): + # ... + + sentry_sdk.init("your dsn", integrations=[DjangoIntegration()]) + +But this will activate, in this case, Sentry even when you're running a +Dev configuration. What you should do instead, is put that code in the +``post_setup`` function. That way Sentry will only ever run when Prod +is the selected configuration: + +.. code-block:: python + + class Prod(Base): + # ... + + @classmethod + def post_setup(cls): + """Sentry initialization""" + super(Prod, cls).post_setup() + sentry_sdk.init( + dsn=os.environ.get("your dsn"), integrations=[DjangoIntegration()] + ) + + .. _project-templates: Project templates @@ -225,6 +261,7 @@ It also works with django-extensions's shell_plus_ management command. .. _`manage your IPython profile`: http://ipython.org/ipython-doc/dev/config/overview.html#configuration-file-location .. _shell_plus: https://django-extensions.readthedocs.io/en/latest/shell_plus.html + FastCGI ------- diff --git a/docs/patterns.rst b/docs/patterns.rst index 791b6ba..6811f98 100644 --- a/docs/patterns.rst +++ b/docs/patterns.rst @@ -10,7 +10,9 @@ Server specific settings ------------------------ For example, imagine you have a base setting class in your **settings.py** -file:: +file: + +.. code-block:: python from configurations import Configuration @@ -24,9 +26,11 @@ file:: class Prod(Base): TIME_ZONE = 'America/New_York' -You can now set the ``DJANGO_CONFIGURATION`` environment variable to one -of the class names you've defined, e.g. on your production server it -should be ``Prod``. In bash that would be:: +You can now set the ``DJANGO_CONFIGURATION`` environment variable to +one of the class names you've defined, e.g. on your production server +it should be ``Prod``. In Bash that would be: + +.. code-block:: console export DJANGO_SETTINGS_MODULE=mysite.settings export DJANGO_CONFIGURATION=Prod @@ -34,32 +38,38 @@ should be ``Prod``. In bash that would be:: Alternatively you can use the ``--configuration`` option when using Django management commands along the lines of Django's default ``--settings`` -command line option, e.g.:: +command line option, e.g. + +.. code-block:: console python manage.py runserver --settings=mysite.settings --configuration=Prod Property settings ----------------- -Use a `property` to allow for computed settings. This pattern can also be used to postpone / lazy evaluate a value. E.g. useful when nesting a Value in a dictionary and a string is required:: +Use a ``property`` to allow for computed settings. This pattern can +also be used to postpone / lazy evaluate a value. E.g., useful when +nesting a Value in a dictionary and a string is required: + +.. code-block:: python class Prod(Configuration): - SENTRY_DSN = values.Value(None, environ_prefix=None) + SOME_VALUE = values.Value(None, environ_prefix=None) @property - def RAVEN_CONFIG(self): + def SOME_CONFIG(self): return { - 'dsn': self.SENTRY_DSN, + 'some_key': self.SOME_VALUE, } - - Global settings defaults ------------------------ -Every ``configurations.Configuration`` subclass will automatically contain -Django's global settings as class attributes, so you can refer to them when -setting other values, e.g.:: +Every ``configurations.Configuration`` subclass will automatically +contain Django's global settings as class attributes, so you can refer +to them when setting other values, e.g. + +.. code-block:: python from configurations import Configuration @@ -77,13 +87,17 @@ Configuration mixins You might want to apply some configuration values for each and every project you're working on without having to repeat yourself. Just define -a few mixin you re-use multiple times:: +a few mixin you re-use multiple times: + +.. code-block:: python class FullPageCaching(object): USE_ETAGS = True Then import that mixin class in your site settings module and use it with -a ``Configuration`` class:: +a ``Configuration`` class: + +.. code-block:: python from configurations import Configuration @@ -97,8 +111,10 @@ Pristine methods .. versionadded:: 0.3 In case one of your settings itself need to be a callable, you need to -tell that django-configurations by using the ``pristinemethod`` decorator, -e.g.:: +tell that django-configurations by using the ``pristinemethod`` +decorator, e.g. + +.. code-block:: python from configurations import Configuration, pristinemethod @@ -108,13 +124,18 @@ e.g.:: def ACCESS_FUNCTION(user): return user.is_staff -Lambdas work, too:: +Lambdas work, too: + +.. code-block:: python from configurations import Configuration, pristinemethod class Prod(Configuration): ACCESS_FUNCTION = pristinemethod(lambda user: user.is_staff) + +.. _setup-methods: + Setup methods ------------- @@ -123,7 +144,9 @@ Setup methods If there is something required to be set up before, during or after the settings loading happens, please override the ``pre_setup``, ``setup`` or ``post_setup`` class methods like so (don't forget to apply the Python -``@classmethod`` decorator):: +``@classmethod`` decorator): + +.. code-block:: python import logging from configurations import Configuration @@ -154,60 +177,26 @@ Of course that won't work for ``post_setup`` since that's when the settings setup is already done. In fact you can easily do something unrelated to settings, like -connecting to a database:: +connecting to a database: - from configurations import Configuration +.. code-block:: python - class Prod(Configuration): - # ... + from configurations import Configuration - @classmethod - def post_setup(cls): - import mango - mango.connect('enterprise') - -This is also good for things like `Sentry -`_. Which require some initialization -to work, but, which you maybe don't want activated on a dev config. - -Intuitively you might want to add this kind of thing like -any other setting:: - - class Prod(Base): + class Prod(Configuration): # ... - EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" - - sentry_sdk.init("your dsn", integrations=[DjangoIntegration()]) - -But this will still activate sentry even when you're running a Dev -configuration. What you should do, is put this in the ``post_setup`` -function. That way sentry will only ever -run when Prod is the selected configuration:: - - class Prod(Base): - # ... - - EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" - @classmethod def post_setup(cls): - """ - Sentry initialization - """ - super(Prod, cls).post_setup() - sentry_sdk.init( - dsn=os.environ.get("your dsn"), integrations=[DjangoIntegration()] - ) - - - + import mango + mango.connect('enterprise') + .. warning:: You could do the same by overriding the ``__init__`` method of your settings class but this may cause hard to debug errors because - at the time the ``__init__`` method is called (during Django startup) - the Django setting system isn't fully loaded yet. + at the time the ``__init__`` method is called (during Django + startup) the Django setting system isn't fully loaded yet. So anything you do in ``__init__`` that may require ``django.conf.settings`` or Django models there is a good chance it @@ -216,15 +205,16 @@ run when Prod is the selected configuration:: .. versionchanged:: 0.4 A new ``setup`` method was added to be able to handle the new - :class:`~configurations.values.Value` classes and allow an in-between - modification of the configuration values. - + :class:`~configurations.values.Value` classes and allow an + in-between modification of the configuration values. Standalone scripts ------------------ -If you want to run scripts outside of your project you need to add these lines -on top of your file:: +If you want to run scripts outside of your project you need to add +these lines on top of your file: + +.. code-block:: python import configurations configurations.setup()