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
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.
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.
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.
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.
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
Now you can change the settings of the packaged APP from settings.py on the Project side. As a flow,
that's all.
Working sample Repository is here
Have a good Django life!