LoginSignup
1
1

More than 3 years have passed since last update.

【 Docker+Nginx+Django+RDS】WEBアプリができるまで③カスタムユーザーを作ってadminにたどり着く

Last updated at Posted at 2020-02-11

前置き

独学で、子供の成長アプリを作った時のことを、記録として残していきます。
間違っているところなどあれば、ご連絡お願いします。
 ①Djangoのようこそページへたどり着くまで
 ②NginxでDjangoのようこそページへたどり着くまで
 ③カスタムユーザーを作ってadminにたどり着く <--ここです
 ④ログインログアウトをしよう
 ⑤ユーザー登録(サインイン)機能を作ろう
 ⑥ユーザーごとのデータ登録できるようにする〜CRU編
 ⑦ユーザーごとのデータ登録できるようにする〜削除編
 ⑧画像ファイルのアップロード
 ⑨身長体重を記録する@一括削除機能つき
 ⑩成長曲線グラフを描いてみよう
 ⑪本番環境へデプロイ+色々手直し

Goal

カスタムユーザー設定を入れて、admin画面までたどり着く

その前に・・・

Djangoの設定を日本版にする。

setting.py
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に作ったことを教えてあげる。

settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users.apps.UsersConfig', #追加
]

カスタムユーザーを作ったので、そのことを教えてあげる。

settings.py
AUTH_USER_MODEL = 'users.User' #追加

ユーザーカスタマイズ

AbstractBaseUserでデフォルトのユーザークラスをオーバーライド。
デフォルトだとID&PASSだが、mailアドレスをID扱いにしている。

users/model.py
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を修正する。

users/admin.py
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が効いてない…
スクリーンショット 2020-02-11 14.39.45.png

静的ファイルの設定

Djangoで参照するSTATIC_ROOTを指定する。

setting.py

STATIC_ROOT = '/static'

DockerでStaticフォルダを指定する。

docker-compose.yml
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が効いた!

スクリーンショット 2020-02-11 15.01.09.png

最後はこんな感じ。

.
├── 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


参考

1
1
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
1