molpako.py

もるぱこのブログです

Django の User モデルを拡張する

これらのサイトを見ながらしていきます。

目標

  • User モデルを拡張して Employee モデルを作成する
  • 追加するフィールドは employee_number (社員番号)
  • employee_number は主キー

方法

ふたつあるそうです。ひとつめは、プロキシモデル を使う方法。ふたつめは、1対1リンク を使う方法。

プロキシモデル

DB に新しいテーブルを作ることなく、モデルを継承できるモデル。DB スキーマに影響を与えずに既存モデルの振る舞いを変更するために使用される。

使いどき
  • DB へ追加情報を格納する必要がないとき
  • 簡単な関数の追加やクエリマネージャーの変更するとき

1対1リンク

  • 通常の Django モデル
  • プロキシモデルとは異なり、自分のテーブルを持つ
  • OneToOneFieldを介して既存モデルと1対1の関係を持つ
使いどき

既存のモデルに関する追加情報を格納したいとき

この1対1モデルはサイトユーザーに関する、認証には関連しない情報を格納することがあるため、しばしばプロファイルモデルと呼ばれます。

今回は、既存の User モデルにフィールドを追加したいので1対1リンクを使用して拡張していきましょう!

1対1リンクを使用した User モデルの拡張

この方法では、既存の User モデルに関連する追加情報を格納する新しいモデルを作成します。

Step1. models.pyに新しいモデルの定義を行う

from django.contrib.auth.models import User

class Employee(models.Model):
    employee_number = models.IntegerField('社員番号', primary_key=True)
    user = models.OneToOneField(User, on_delete=models.CASCADE)

employee_numerが目的にあった、User に追加したい情報の社員番号です。 userauth.models.Userとの1対1リンクを持っています。

Step2. create_userし、拡張した変数を設定する

from django.contrib.auth.models import Employee, User

user = User.objects.create_user('molpako', 'molpako@mail.address', 'password')
employee = Employee.objects.create(user=user, employee_number=22)

Step3. userからemployee_numberにアクセスできるか確認する

print(user.employee.employee_numer)
22

OK!!
最後に、きちんと主キーになっているかテストコードを書いてみしょう

テストケースを書く書く

今回のテストケースは

  • employee_numberはユニークキーか
  • employee_numberからUserオブジェクトをもってこれるか

です。

テストコード(sandbox/tests.py)は以下になりました。

from django.test import TestCase
from django.contrib.auth.models import User
from django.db.utils import IntegrityError
from .models import Employee


class EmployeeModelTests(TestCase):

def test_employee_number_is_unique(self):
    """
    社員番号が同じにならないこと
    """

    user01 = User.objects.create_user('molpako01', 'molopako@mail.address', 'password')
    user02 = User.objects.create_user('molpako02', 'molopako@mail.address', 'password')

    employee01 = Employee.objects.create(user=user01, employee_number=22)

    with self.assertRaises(IntegrityError):
        Employee.objects.create(user=user02, employee_number=22)

def test_get_uesr_from_employee_number(self):
    """
    社員番号からユーザーを取得する
    """

    user = User.objects.create_user('molpako', 'molopako@mail.address', 'password')
    employee = Employee.objects.create(user=user, employee_number=22)

    self.assertEqual(Employee.objects.get(employee_number=22).user, user)

それでは実行してみます!

$ python manage.py test sandbox
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
..
----------------------------------------------------------------------
Ran 2 tests in 0.293s

OK
Destroying test database for alias 'default'...

楽しい!