Django

Djangoでカスタムユーザーモデルを継承したモデルを作成する方法

・各モデルを定義
 →カスタムUserモデル
 →Studentモデル(Userモデルを継承)
 →Teacherモデル(Userモデルを継承)

・マイグレートして生成したテーブルを確認

・コンソールで色々試してみる

各モデルを定義

Userモデル

from django.db import models
from django.contrib.auth.models import (
    BaseUserManager,
    AbstractBaseUser,
    PermissionsMixin
)

class UserManager(BaseUserManager):

    def create_user(self, email, password=None, **extra_fields):
        """ユーザー作成"""
        if not email:
            raise ValueError('Email must be .')

        user = self.model(
            email=self.normalize_email(email),
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        """createsuperuserコマンドによるユーザー作成"""
        user = self.create_user(email, password)
        user.is_staff = True  # avalilable admin site ?
        user.is_superuser = True
        user.save(using=self._db)
        return user


class User(AbstractBaseUser, PermissionsMixin):
    class Meta:
        db_table = 'users'
        # abstract = True # create table ?

    email = models.EmailField(verbose_name='メールアドレス', max_length=50, unique=True)
    is_active = models.BooleanField(default=True) # available login ?
    is_staff = models.BooleanField(default=False) # avalilable admin site ?

    objects = UserManager()

    USERNAME_FIELD = 'email' # change column for authentication ( username -> email )

    def __str__(self):
        return self.email

Studentモデル

from django.db import models
from .models import User # 作成したカスタムUserモデル


class Student(User):
    class Meta:
        db_table = 'students'

    name = models.CharField(verbose_name='名前', max_length=30)

    def __str__(self):
        return self.name

Teacherモデル

from django.db import models
from .models import User # 作成したカスタムUserモデル


class Teacher(User):
    class Meta:
        db_table = 'teachers'

    name = models.CharField(verbose_name='名前', max_length=30)
    age = models.IntegerField( verbose_name='年齢', null=True, blank=True)

    def __str__(self):
        return self.name

マイグレートして生成したテーブルを確認

レコードに関しては、はDjangoの管理画面などからいくつか登録してみてください。

$ python manage.py makemigrations
$ python manage.py migrate

>> use [ データベース名 ];
>> show tables;

 +--------------------------+
 | auth_group
 | auth_group_permissions
 | auth_permission
 | django_admin_log
 | django_content_type
 | django_migrations
 | django_session
 | students
 | teachers
 | users
 | users_groups
 | users_user_permissions
 +--------------------------+

usersテーブルで表示されるカラムは以下のようになってると思います。

mysql> select * from users;

id | password | last_login | is_superuser | email | is_active | is_staff
1  |〜〜〜〜〜〜〜〜〜| yuya@gmail.com | 〜〜〜〜〜〜〜〜
2  |〜〜〜〜〜〜〜〜〜| johnson@gmail.com | 〜〜〜〜〜〜〜〜

studentsテーブル、teachersテーブルです。

mysql> select * from students;

+----------------+---------------+
| user_ptr_id |        name |
+----------------+---------------+
|               1 |          yuya |
+----------------+---------------+

mysql> select * from teachers;

+----------------+---------------+---------------+
| user_ptr_id |        name |           age |
+----------------+---------------+---------------+
|               2 |     johnson |            30 |
+----------------+---------------+---------------+

コンソールで色々試してみる

‘tanaka’を取りだしてみる

$ python manage.py shell

>>> from .models import User
>>> from .models import Teacher

>>> u = User.objects.get(email='登録したメールアドレス')
>>> t = Teacher.objects.get(user_ptr_id=u.pk)
>>> t.name
>>> 'tanaka'

user_ptr_idについては、暗黙的なOneToOneFieldのイメージです。

このカラムがPrimary Keyの役割をし、またusersテーブルの対応するレコードのid(Primary Key)と一致します。

COMMENT

メールアドレスが公開されることはありません。