1
0

More than 3 years have passed since last update.

Django: 再利用可能なAPPの設定をDjangoRestFrameWorkにならって実装

Last updated at Posted at 2019-11-11

Django: 再利用可能なAPPの設定をDjangoRestFrameWorkにならって実装

Djangoで開発しはじめて、再利用可能なAPPを作り別のProjectでInstallしたときに、APPで設定しているデフォルトの設定が変更できない....
となったのでアプリケーションごとの設定をproject/settings.pyから変更できる方法を探していました。
Django Rest Framework にいいコードがあったので、参考にやってみました。

簡単な Todo Task Api を例にやってみます。

動くサンプルのRepositoryはこちらから

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
}

...

こんな感じで変更してはりました。
これでPaginationを使ったときに、PAGE_SIZEを変更できたりします。

Todo Task Api での例

では実際に簡単なTodo Task Apiでの動作の例を見てみましょう。

Modelは下記の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がAPPの設定値を参照できるインスタンスです。
api_settings.KEYで値を取得できます。

今回の例では下記の二つをsettings.pyで変更できます。
- title: max_length
- status: choices

例えばTASK_STATUS_CHOICESのデフォルトの設定値がtodo_api/settings.pyで下記の通りに設定されているとします。

todo_api/settings.py

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

...

これを変更する場合はproject/settings.pyを変更することで可能になります。

project/settings.py

...

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

上記のコードを追加することでタスクのステータスの選択肢にNEW_STATUSを追加することができます。

では実際に詳細なコードを見ていきましょう。

APISettings クラス

Django Rest Frameworkを参考にAPISettings クラスをすごく簡略化して作成しました。

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]

getattrメソッドを使用しているのが重要です。

これにより、api_settings.KEYで設定にアクセスすることができます。

self._user_settingsにはproject/settings.pyで設定されているsetting_root_name以下の値が代入されます。

APP側の settings.py

では先ほど作成したAPISettingsを使用して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)

APISettingsの第一引数に設定のルート名を、第二引数にデフォルトの設定値を渡して生成します。

これで設定が完了しました。

使用する

先ほど作成したTODO_API用の設定を使用するには、Importしてアクセスするだけです。

todo_api/models.py

from .settings import api_settings

print(api_settings.TASK_TITLE_MAX_LENGTH)
# > 30

まとめ

これで、Package化したAPPの設定をProject側のsettings.pyから変更できるようになりました。
流れとしては、
1. APISettingsクラスをコピペ
2. APP設定のルート名を決める
3. APP側のsettings.pyでDefaultを定義
4. APP側のsettings.pyでAPISettingsのインスタンスを作成
5. 使用する

以上です。

動くサンプルのRepositoryはこちらから

ではでは、よいDjangoライフを!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0