[PYTHON] Django: Implement reusable APP settings following Django RestFrameWork

Django: Implement reusable APP settings following Django RestFrameWork

When I start developing with Django, create a reusable APP and install it in another project, I can't change the default settings set in the APP ... So I was looking for a way to change the settings for each application from ** project / settings.py **. There was good code in ** Django Rest Framework **, so I tried it as a reference.

Let's take a simple ** Todo Task Api ** as an example.

Working sample Repository is here

Example with Django Rest Framework

project/settings.py



...

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10
}

...

I changed it like this. Now you can change PAGE_SIZE when using Pagination.

Example in Todo Task Api

Let's take a look at a really simple example of how it works with the Todo Task API.

** Model ** is only the following Task.

todo_api/models.py



from django.db import models
from .settings import api_settings


class Task(models.Model):
    title = models.CharField(max_length=api_settings.TASK_TITLE_MAX_LENGTH)
    status = models.IntegerField(choices=api_settings.TASK_STATUS_CHOICES)
    

** todo_api.settings.api_settings ** is the instance that can refer to the setting value of APP. You can get the value with ** api_settings.KEY **. In this example, the following two can be changed in settings.py.

For example, assume that the default setting value of ** TASK_STATUS_CHOICES ** is set as follows in todo_api / settings.py.

todo_api/settings.py



DEFAULTS = {
    'TASK_TITLE_MAX_LENGTH': 30,
    'TASK_STATUS_CHOICES': [
        (1, 'TODO'),
        (2, 'DOING'),
        (3, 'DONE'),
    ]
}

...

If you want to change this, you can change it by changing project / settings.py.

project/settings.py



...

TODO_API = {
    'TASK_STATUS_CHOICES': [
        (1, 'TODO'),
        (2, 'DOING'),
        (3, 'DONE'),
        (4, 'NEW_STATUS'),
    ],
}

You can add ** NEW_STATUS ** to the task status choices by adding the above code. Let's actually look at the detailed code.

APISettings class

I created the ** APISettings ** class in a very simplified way with reference to ** Django Rest Framework **.

utils/api_settings.py



from django.conf import settings


class APISettings:
    """
    A settings object, that allows API settings to be accessed as properties.

    Set default settings in your app settings.py like this:
        from app_utils.setting import APISettings
        api_settings = APISettings('TODO_API', DEFAULTS)

    For example:

        from todo_api.settings import api_settings
        print(api_settings.TASK_STATUS_CHOICES)

    """

    def __init__(self, setting_root_name, defaults):
        self._setting_root_name = setting_root_name
        self._defaults = defaults
        self._user_settings = getattr(settings, self._setting_root_name, {})

    def __getattr__(self, item):
        if item not in self._defaults:
            raise AttributeError("Invalid {} setting: {}".format(self._setting_root_name, item))

        try:
            return self._user_settings[item]
        except KeyError:
            return self._defaults[item]

It is important to use the getattr method. This will allow you to access your settings with api_settings.KEY. ** self._user_settings ** is assigned the value below ** setting_root_name ** set in project / settings.py.

APP side settings.py

Now, let's use the ** API Settings ** created earlier to ** create a configuration instance for TODO APP **.

todo_api/settings.py



from utils.app_setting import APISettings

DEFAULTS = {
    'TASK_TITLE_MAX_LENGTH': 30,
    'TASK_STATUS_CHOICES': [
        (1, 'TODO'),
        (2, 'DOING'),
        (3, 'DONE'),
    ],
}

api_settings = APISettings('TODO_API', DEFAULTS)

Generate by passing ** the root name of the setting ** as the first argument of APISettings and ** the default setting value ** as the second argument.

This completes the settings.

use

To use the settings for TODO_API created earlier, just import and access.

todo_api/models.py



from .settings import api_settings

print(api_settings.TASK_TITLE_MAX_LENGTH)
# > 30

Summary

Now you can change the settings of the packaged APP from settings.py on the Project side. As a flow,

  1. Copy the APISettings class
  2. Decide the root name of the APP setting
  3. Define Default in settings.py on the APP side
  4. Create an instance of APISettings in settings.py on the APP side
  5. Use

that's all.

Working sample Repository is here

Have a good Django life!

Recommended Posts

Django: Implement reusable APP settings following Django RestFrameWork
Implement a Django app on Hy
django default settings
Django + MySQL settings
Django URL settings
Launch my Django app
Initialize your Django app
Django command completion settings