前置き
独学で、子供の成長アプリを作った時のことを、記録として残していきます。
間違っているところなどあれば、ご連絡お願いします。
①Djangoのようこそページへたどり着くまで
②NginxでDjangoのようこそページへたどり着くまで
③カスタムユーザーを作ってadminにたどり着く <--ここです
④ログインログアウトをしよう
⑤ユーザー登録(サインイン)機能を作ろう
⑥ユーザーごとのデータ登録できるようにする〜CRU編
⑦ユーザーごとのデータ登録できるようにする〜削除編
⑧画像ファイルのアップロード
⑨身長体重を記録する@一括削除機能つき
⑩成長曲線グラフを描いてみよう
⑪本番環境へデプロイ+色々手直し
Goal
カスタムユーザー設定を入れて、admin画面までたどり着く
その前に・・・
Djangoの設定を日本版にする。
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
まずはユーザー管理用のアプリを作る
startappでusersアプリを作る。
docker-compose run web python ./manage.py startapp users
すると、こんな感じになる。
.
├── docker-compose.yml
├── nginx
│ ├── conf
│ │ └── mysite_nginx.conf
│ └── uwsgi_params
├── src
│ ├── manage.py
│ ├── mysite
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-37.pyc
│ │ │ ├── settings.cpython-37.pyc
│ │ │ ├── urls.cpython-37.pyc
│ │ │ └── wsgi.cpython-37.pyc
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── static
│ └── users
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── web
├── Dockerfile
└── requirements.txt
Djangoでアプリを作ったら、settingに作ったことを教えてあげる。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users.apps.UsersConfig', #追加
]
カスタムユーザーを作ったので、そのことを教えてあげる。
AUTH_USER_MODEL = 'users.User' #追加
ユーザーカスタマイズ
AbstractBaseUserでデフォルトのユーザークラスをオーバーライド。
デフォルトだとID&PASSだが、mailアドレスをID扱いにしている。
from django.db import models
from django.core.mail import send_mail
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.contrib.auth.base_user import BaseUserManager
class UserManager(BaseUserManager):
"""ユーザーマネージャー."""
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""Create and save a user with the given username, email, and
password."""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
"""カスタムユーザーモデル."""
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
"""Return the first_name plus the last_name, with a space in
between."""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
モデルを追加したら、adminを修正する。
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import ugettext_lazy as _
from .models import User
class MyUserChangeForm(UserChangeForm):
class Meta:
model = User
fields = '__all__'
class MyUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ('email',)
class MyUserAdmin(UserAdmin):
fieldsets = (
(None, {'fields': ('email', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
form = MyUserChangeForm
add_form = MyUserCreationForm
list_display = ('email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('email', 'first_name', 'last_name')
ordering = ('email',)
admin.site.register(User, MyUserAdmin)
モデルを作ったら、migrationする。
docker-compose run web python ./manage.py makemigrations
docker-compose run web python ./manage.py migrate
superユーザー作成
docker-compose run web python ./manage.py createsuperuser
createsuperuserを入れると、ID (今回だとメールアドレス)とPasswordを求められる。
管理者権限のユーザーなので、秘密にする。
メールアドレス: admin@example.com
Password:
Password (again):
Superuser created successfully.
Dockerで立ち上げよう①
Dockerを起動
docker-compose up
localhost:8000/adminへアクセスする。
表示されるけど、CSSが効いてない…
静的ファイルの設定
Djangoで参照するSTATIC_ROOTを指定する。
STATIC_ROOT = '/static'
DockerでStaticフォルダを指定する。
version: "3"
services:
nginx:
image: nginx:1.13
ports:
- "8000:8000"
volumes:
- ./nginx/conf:/etc/nginx/conf.d
- ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
- ./static:/static
depends_on:
- web
db-postgres:
image: postgres
web:
build: ./web
volumes:
- ./src:/code
- ./static:/static #ここを追加
expose:
- "8000"
depends_on:
- db-postgres
command: uwsgi --socket :8000 --module mysite.wsgi
collectstaticでプロジェクト内に入っているSTATICファイルの中身を
最上位のSTATICに集約する。
docker-compose run web python ./manage.py collectstatic
Dockerで立ち上げよう②
localhost:8000/adminへアクセスする。
ちゃんとCSSが効いた!
最後はこんな感じ。
.
├── docker-compose.yml
├── nginx
│ ├── conf
│ │ └── mysite_nginx.conf
│ └── uwsgi_params
├── src
│ ├── manage.py
│ ├── mysite
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-37.pyc
│ │ │ ├── settings.cpython-37.pyc
│ │ │ ├── urls.cpython-37.pyc
│ │ │ └── wsgi.cpython-37.pyc
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
│ ├── static
│ └── users
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-37.pyc
│ │ ├── admin.cpython-37.pyc
│ │ ├── apps.cpython-37.pyc
│ │ └── models.cpython-37.pyc
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-37.pyc
│ │ └── __init__.cpython-37.pyc
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── static
│ └── admin
│ ├── css
│ │ ├── autocomplete.css
│ │ ├── base.css
│ 〜〜〜この中にいっぱい入っている。省略。
└── web
├── Dockerfile
└── requirements.txt
参考