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 に追加したい情報の社員番号です。
user
はauth.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'...
楽しい!