見出し画像

【タレントダッシュボード構築 #3】djangoのモデル定義を理解する②

#2に続き、今回はdjangoのモデル定義、特にForeignKey型についてまとめます。

テーブル定義

まずは、社員の基礎情報を集めるテーブルを定義します。
キーは社員コード、属性としていくつかの情報を持たせ、ここにForeignKey型の項目も定義します。

[models.py]

class Evaluation(models.Model):
   """
   クラス(考課)
   """
   code_7_ev = models.CharField(verbose_name='社員コード',max_length=7,primary_key=True,)
   ev_03 = models.CharField(verbose_name='03回前考課',max_length=10,blank=True,null=True,)
   ev_02 = models.CharField(verbose_name='02回前考課',max_length=10,blank=True,null=True,)
   ev_01 = models.CharField(verbose_name='01回前考課',max_length=10,blank=True,null=True,)  
   
   # 管理サイト上の表示設定
   def __str__(self):
       return self.code_7_ev

   class Meta:
       verbose_name = '考課'
       verbose_name_plural = '考課'

class Item(models.Model):
   """
   クラス(社員基礎情報)
   """
   code_7 = models.CharField(verbose_name='社員コード',max_length=7,primary_key=True,)
   name = models.CharField(verbose_name='氏名',max_length=30,)
   name_kana = models.CharField(verbose_name='カナ氏名',max_length=30,)
   honbu = models.CharField(verbose_name='本部',max_length=30,)
   dept = models.CharField(verbose_name='部室',max_length=30,)
   evaluation = models.ForeignKey(Evaluation,on_delete=models.SET_NULL,null=True,blank=True,)

   # 管理サイト上の表示設定
   def __str__(self):
       return self.name

   class Meta:
       verbose_name = '社員基礎情報'
       verbose_name_plural = '社員基礎情報'

Evaluationクラスでは、code_7_evをprimary_keyとして定義します。どちらも社員コードで一意になるテーブルになるので、リレーションは1:1ということになります。
※もちろん、項目名はリレーション元・リレーション先で共通でも問題ありません。混乱を防ぐ意味で、念のため別名にしています。

また、当然ですが、リレーション先のテーブルを先に定義しないとエラーになります。上記の例でItem、Evaluationの順に定義してしまうと、NameErrorが吐かれます。

NameError: name 'Evaluation' is not defined

リレーション元、上記の例ではItemクラスで、ForeignKey項目の引数は以下の通り。

(to, on_delete, **options)

toはリレーション先のテーブルです。
on_deleteでは、リレーションを張った先のレコードを削除しようとしたときの挙動を指定します。以下の中から選択します。

CASCADE:連鎖してレコードを削除する。
PROTECT:削除を試みた場合、ProtectedErrorを吐く。削除させない。
SET_NULL:リレーション元の項目にNULLを設定する。
SET_DEFAULT:デフォルト値を設定する。※defaultオプションを同時に設定する必要あり
SET():指定した値を設定する。
DO_NOTHING:何もしない。

さて、うまくリレーションを張れているか確認しましょう。
同じキーを持つデータを入れます。SQLでDBに直接insertしても良いのですが、件数が少ない場合は、管理画面から入力するのが楽です。

管理画面での操作を可能にする

models.pyでテーブルを定義しただけでは管理画面から操作ができません。
操作可能にするため、admin.pyを編集します。

[admin.py]

from django.contrib import admin
from .models import Item, Evaluation

@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
   class Meta:
       verbose_name = '社員基礎情報'
       verbose_name_plural = '社員基礎情報'

@admin.register(Evaluation)
class ItemAdmin(admin.ModelAdmin):
   class Meta:
       verbose_name = '考課'
       verbose_name_plural = '考課'

ファイルを保存すると、こんな感じで管理画面にテーブルが表示されます。

「追加」ボタンを押すとこんな感じ。中身を入力して保存しましょう。

「保存」ボタンを押すと…

1件追加されました。
リレーション先である考課情報も追加します。

もう一度「社員基礎情報」を参照してみます。

Evaluation のプルダウンメニューに、先ほど入力した考課情報のキーが表示されるようになりました。
これを選択すると、リレーションを張ることができます。
モデルの定義をしただけでは勝手にリレーションが張られないことに注意が必要です。

【hint】
管理画面でレコードを追加しようとすると、以下のエラーメッセージが出力される場合があります。
django.db.utils.OperationalError: no such table: main.auth_user__old

これは、Django Version 2.1.4 で発生する不具合です。
djangoのバージョンアップを行ったうえで、すべてのマイグレーションファイルを削除し、sqlite3の実体を削除してマイグレーションをやり直すと解決します。

# djangoバージョンアップ
pip install --upgrade django

# マイグレーションファイル削除
rm -d -r migrations/     # アプリケーションディレクトリで実行

# sqlite3の実体削除
rm -d -r db.sqlite3      # データベースの実体があるディレクトリで実行

今回は以上です。
次回以降、実際のweb画面の構築に入っていきます。

この記事が気に入ったらサポートをしてみませんか?