はじめに
LINE Messaging APIなど、APIを利用したDjangoアプリを個人開発する際、APIのキー情報を
- Herokuなどの本番環境では環境変数に設定
- ローカルの開発環境ではlocal_settings.pyに直書き
して管理する方法を採ったので、その方法をまとめます。
そのような管理にした理由
-
GitHubで公開するソースコード(local_settings.py以外)では、APIのキーを秘匿したい
-
開発環境であるMacではAPI利用アプリを複数開発するので、APIのキーを環境変数ではなく、Djangoプロジェクト単位のファイル(local_settings.py)で管理したい
-
views.pyやmodels.pyなどではAPIのキーをどこから読み込んでいるか意識させない作りにしたい(本番環境と開発環境でロジックに差をつけたくない)
為です。
環境
- Python 3.6.6
- Django 2.1.5
settings.pyとlocal_settings.pyでのAPIキーの設定方法
local_settings.pyでは、DEBUG = True
にしつつ、各APIのキーを直書きします。
# ...
DEBUG = True
SECRET_KEY = 'hogehogehoge...'
LINE_CHANNEL_ACCESS_TOKEN = 'hogehogehoge...'
LINE_CHANNEL_SECRET = 'hogehogehoge...'
settings.pyでは、DEBUG = False
にした上で、local_settings.pyを読みに行かせ、local_settings.pyの存在しない本番環境であれば(DEBUG = True
にならなければ)、各APIキーを本番環境の環境変数から読み込みます。
# ...
DEBUG = False
# ...
try:
from .local_settings import *
except ImportError:
pass
if not DEBUG:
SECRET_KEY = os.environ['SECRET_KEY']
LINE_CHANNEL_ACCESS_TOKEN = os.environ['LINE_CHANNEL_ACCESS_TOKEN']
LINE_CHANNEL_SECRET = os.environ['LINE_CHANNEL_SECRET']
views.pyやmodels.pyなどで、APIのキーを使う
settings.py(local_settings.py)で設定した変数は、
from django.conf import settings
print(settings.LINE_CHANNEL_ACCESS_TOKEN)
とすることで、views.pyやmodels.pyなどから参照することができます。
以下はviews.pyにおいて、LINE Messaging APIのキーを使用している例です。
APIのキーを環境変数から読むのかファイルから読むのか、はsettings.py側で制御しているので、views.py側では意識する必要がなくなりました。
from django.http import HttpResponse, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import (
MessageEvent,
TextMessage,
TextSendMessage
)
# settings.pyに設定したAPIキーを参照
line_bot_api = LineBotApi(channel_access_token=settings.LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(channel_secret=settings.LINE_CHANNEL_SECRET)
@csrf_exempt
def callback(request):
signature = request.META['HTTP_X_LINE_SIGNATURE']
body = request.body.decode('utf-8')
try:
handler.handle(body, signature)
except InvalidSignatureError:
return HttpResponseForbidden()
return HttpResponse('OK', status=200)
# ...