はじめに
前回の続きです。
前の記事: Docker+Django+Next+TypeScript+ECSでアプリを作った話(1) ~ 準備編 ~
次の記事: Docker+Django+Next+TypeScript+ECSでアプリを作った話(3) ~ Djangoのスキーマ作成からデータ取得まで~
今回はDjangoプロジェクトの初期設定から、Model作成までを書きました。
バックエンドとしてDjangoを採用しましたが、DjangoをAPI化するのにgraphene-djangoを採用しました。
graphene-djangoに関しては以下の記事を参考にさせていただきました。
1.初期設定
開発・テスト環境用と本番環境用のsettingsを作成します。また、本番環境用にSECRET_KEYを管理する.envを作成し、django-environというパッケージにて管理します。
myProject/
app/
+ .env
app/
settings.py
+ dev_settings.py
+ prod_settings.py
...
- settings.py
全ての開発環境で共通する部分を記載しています。SECRET_KEYやDEBUGは環境別settingsに記載しています。
ALLOWED_HOSTSは環境ごとに変更できるように、環境変数を入れています。
その他に、graphene-djangoとDBの設定の変更や、言語設定を日本語に、タイムゾーンを日本に変更しています。
また、AUTH_USER_MODELを後に作成するUserモデルに設定しています。
+ import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
-
- SECRET_KEY = '1234567890**************************'
- DEBUG = True
-
- ALLOWED_HOSTS = []
+ ALLOWED_HOSTS = [os.environ['ALLOWED_HOST']]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'graphene_django',
+ 'corsheaders',
+ 'api.apps.ApiConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ 'corsheaders.middleware.CorsMiddleware',
]
+
+ CORS_ORIGIN_WHITELIST = [
+ os.environ['FRONT_URI']
+ ]
+
+ GRAPHWL_JWT = {
+ 'JWT_VERIFY_EXPORATION': False,
+ }
+
+ GRAPHENE = {
+ 'SCHEMA':
+ 'app.schema.schema',
+ 'MIDDLEWARE': [
+ 'graphql_jwt.middleware.JSONWebTokenMiddleware',
+ ],
+ }
+
+ AUTHENTICATION_BACKENDS = [
+ 'graphql_jwt.backends.JSONWebTokenBackend',
+ 'django.contrib.auth.backends.ModelBackend',
+ ]
ROOT_URLCONF = 'app.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'app.wsgi.application'
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
+ 'ENGINE': 'django.db.backends.postgresql',
- 'NAME': BASE_DIR / 'db.sqlite3',
+ 'NAME': os.environ['DB_NAME'],
+ 'USER': os.environ['DB_USER'],
+ 'HOST': os.environ['DB_HOST'],
+ 'PORT': 5432,
}
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
- LANGUAGE_CODE = 'en-us'
+ LANGUAGE_CODE = 'ja'
-
- TIME_ZONE = 'UTC'
+ TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
+
+ AUTH_USER_MODEL = 'api.CustomUser'
STATIC_URL = '/static/'
+
+ STATIC_ROOT = os.path.join(BASE_DIR, 'static')
- dev_settings.py
開発環境、テスト環境用のsettingsを記載しています。
SECRET_KEYは本番環境とは異なる値にしています。
from .settings import *
DEBUG = True
SECRET_KEY = '1234567890**************************'
- prod_settings.py
本番環境用のsettingsを記載しています。
SECRET_KEYはdjango-environにて.envに記載しています。
import os
import environ
from .settings import *
env = environ.Env()
env.read_env(os.path.join(BASE_DIR, '.env'))
DEBUG = False
SECRET_KEY = env('SECRET_KEY')
- .env
本番環境用のSECRET_KEYを記載しています。
SECRET_KEY=abcdefghijk************************
2.Model作成
UserモデルとProfileモデルを作成します。
apiフォルダ直下のmodels.pyに記載します。
- models.py
UserモデルはDjango標準のAbstractBaseUserをオーバーライドして作成します。
email、passwordでの認証にするため、name属性はProfileモデルに分け、Userモデルは必要最低限の属性にしています。
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('email is must')
user = self.model(email=self.normalize_email(email))
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
user = self.create_user(email, password)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=50, unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
class Profile(models.Model):
nickname = models.CharField(max_length=20)
user = models.OneToOneField(
CustomUser, related_name="profile",
on_delete=models.CASCADE
)
def __str__(self):
return self.nickname
- admin.py
Django標準の管理画面にてUserモデルとProfileモデルをCRUD操作できるように記載します。
from django.contrib import admin
from .models import CustomUser, Profile
admin.site.register(CustomUser)
admin.site.register(Profile)
- docker-compose.yml
Djangoコンテナ起動時に、開発環境用のsettingsを使用するように修正します。
version: "3"
services:
app:
build:
context: .
ports:
- "8000:8000"
volumes:
- ./app:/app
- command: sh -c "python manage.py migrate &&
- python manage.py runserver 0.0.0.0:8000"
+ command: sh -c "python manage.py migrate --settings app.dev_settings &&
+ python manage.py runserver 0.0.0.0:8000 --settings app.dev_settings"
environment:
- FRONT_URI=http://localhost:3000
- ALLOWED_HOST=localhost
- DB_HOST=db
- DB_NAME=app
- DB_USER=postgres
- DB_PASS=supersecretpassword
depends_on:
- db
・・・
以下のコマンドにて、DBを更新して、管理者ユーザーを作成します。
$ make migrate
$ make admin
コンテナを再起動して、localhost:8000/adminにアクセスします。
コンテナが正しく動作していれば、管理者用のログインページが表示されるので、
先ほど作成した管理者にてログインします。
ログインすると、UserモデルとProfileモデルのCRUD操作ができるページに遷移します。
まとめ
今回はsettingsの修正と UserモデルとProfileモデルの作成をしました。
次回はDjangoをGraphqlとして、スキーマを作成して、ブラウザでデータを取得する所までを書きたいと思います。
次の記事: Docker+Django+Next+TypeScript+ECSでアプリを作った話(3) ~ Djangoのスキーマ作成からデータ取得まで~