View on GitHub

モデルの定義

Home

モデルの定義

これまでに作成したユーザ、アイテム、評価値テーブルと、各推薦リストテーブルに対応したモデルを定義します。モデルクラスは、recsys_django/online/models.pyに記述します。作成した各テーブルのモデルの定義は下記のコマンドで確認できます。

(venv_recsys_django) $ export DB_USER=rsl
(venv_recsys_django) $ export DB_PASSWORD=【パスワード】
(venv_recsys_django) $ python manage.py inspectdb

上記のコマンドを実行した結果、出力される内容を参考にモデルクラスを定義しましょう。online/models.pyに下記のコードを記述してください。

リスト1: recsys_django/online/models.py

from django.db import models


class User(models.Model):
    """ユーザモデル

    Attributes
    ----------
    user_id : IntegerField
        ユーザID
    name : TextField
        ユーザ名
    age : IntegerField
        年齢
    sex : CharField
        性別
    """
    user_id = models.IntegerField(primary_key=True)
    name = models.TextField()
    age = models.IntegerField(blank=True, null=True)
    sex = models.CharField(max_length=1, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'users'

    def __str__(self):
        return '{}:{}'.format(self.user_id, self.name)


class Item(models.Model):
    """アイテムモデル

    Attributes
    ----------
    item_id : IntegerField
        アイテムID
    name : TextField
        アイテム名
    red : IntegerField
        赤身の特徴量
    white : IntegerField
        白身の特徴量
    shining : IntegerField
        光物の特徴量
    """
    item_id = models.IntegerField(primary_key=True)
    name = models.TextField()
    red = models.IntegerField(blank=True, null=True)
    white = models.IntegerField(blank=True, null=True)
    shining = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'items'

    def __str__(self):
        return '{}:{}'.format(self.item_id, self.name)


class Rating(models.Model):
    """評価値モデル

    Attributes
    ----------
    user : ForeignKey[User]
        対象ユーザ
    item : ForeignKey[Item]
        対象アイテム
    rating : IntegerField
        評価値
    """
    user = models.ForeignKey(User, models.CASCADE)
    item = models.ForeignKey(Item, models.CASCADE)
    rating = models.IntegerField()

    class Meta:
        managed = False
        db_table = 'ratings'

    def __str__(self):
        return '{}:{}:{}'.format(self.user_id, self.item_id, self.rating)


class ReclistPopularity(models.Model):
    """人気ベース推薦リストモデル

    Attributes
    ----------
    rank : FloatField
        推薦順位
    item : ForeignKey[Item]
        推薦アイテム
    score : FloatField
        推薦スコア
    """
    rank = models.FloatField()
    item = models.ForeignKey(Item, models.CASCADE)
    score = models.FloatField()

    class Meta:
        managed = False
        db_table = 'reclist_popularity'

    def __str__(self):
        return '{}:{}:{}'.format(self.rank, self.item, self.score)


class ReclistSimilarity(models.Model):
    """アイテム類似度ベース推薦リストモデル

    Attributes
    ----------
    base_item : ForeignKey[Item]
        ベースアイテム
    rank : FloatField
        推薦順位
    item : ForeignKey[Item]
        推薦アイテム
    score : FloatField
        推薦スコア
    """
    base_item = models.ForeignKey(Item, models.CASCADE, related_name='base_item')
    rank = models.FloatField()
    item = models.ForeignKey(Item, models.CASCADE)
    score = models.FloatField()

    class Meta:
        managed = False
        db_table = 'reclist_similarity'

    def __str__(self):
        return '{}:{}:{}:{}'.format(self.base_item, self.rank, self.item, self.score)


class ReclistItemcf(models.Model):
    """アイテムベース協調フィルタリングに基づく推薦リストモデル

    Attributes
    ----------
    user : ForeignKey[User]
        対象ユーザ
    rank : FloatField
        推薦順位
    item : ForeignKey[Item]
        推薦アイテム
    score : FloatField
        推薦スコア
    """
    user = models.ForeignKey(User, models.CASCADE)
    rank = models.FloatField()
    item = models.ForeignKey(Item, models.CASCADE)
    score = models.FloatField()

    class Meta:
        managed = False
        db_table = 'reclist_itemcf'

    def __str__(self):
        return '{}:{}:{}:{}'.format(self.user, self.rank, self.item, self.score)

online/models.pyではdjango.db.models.Modelクラスを継承した各モデルを定義しています。ユーザモデル、アイテムモデル、評価値モデルは、それぞれUserItemRatingクラスとして定義しています。また、各推薦リストモデルはReclist*クラスとして定義しています。

テーブルのカラムはモデルクラスのクラス属性として定義します。例えば、Userクラスにはnameを定義しています。このクラス属性はFieldクラスのインスタンスとして定義します。TextFieldはテキストフィールドを表します。必要に応じて、blanknullなどのFieldクラスのフィールドオプションを指定します。なお、ユーザテーブルとアイテムテーブルにおいては、それぞれuser_iditem_idのカラムを主キーとして設定しました。これらに対応して、UserモデルとItemモデルでは、それぞれに対応するフィールドとしてuser_iditem_idのフィールドオプションにprimary_key=Trueを設定しています。一方で、RatingモデルやReclist*モデルにおいては、明示的には主キーに対応するフィールドを定義していません。主キーフィールドの定義を省略すると、自動的にidという名前で主キーフィールドが追加されます。

モデルについては、文献[1][2]を参照してください。

モデルの準備ができましたので、マイグレーションを実行します。まず、下記のコマンドでマイグレーションファイルを作成します。

(venv_recsys_django) $ python manage.py makemigrations online
Migrations for 'online':
  online/migrations/0001_initial.py
    - Create model Item
    - Create model Rating
    - Create model ReclistItemcf
    - Create model ReclistPopularity
    - Create model ReclistSimilarity
    - Create model User

recsys_django/online/migrations/ディレクトリに0001_initial.pyが作成されました。下記のコマンドでマイグレーションが実行する内容を確認してみましょう。

(venv_recsys_django) $ python manage.py sqlmigrate online 0001
BEGIN;
--
-- Create model Item
--
--
-- Create model Rating
--
--
-- Create model ReclistItemcf
--
--
-- Create model ReclistPopularity
--
--
-- Create model ReclistSimilarity
--
--
-- Create model User
--
COMMIT;

このようにSQLが出力されました。ただし、今回はいずれも既にテーブルを作成済みですので、マイグレーションにより新規にテーブルが作成されることはありません。では、マイグレーションを実行してみましょう。

(venv_recsys_django) $ python manage.py migrate
Operations to perform:
  Apply all migrations: accounts, admin, auth, contenttypes, online, sessions
Running migrations:
  Applying online.0001_initial... OK

マイグレーションの詳細は文献[2][3]を参照してください。

参考

  1. はじめての Django アプリ作成、その2 | Django ドキュメント | Django # モデルの作成
  2. 現場で使える Django の教科書《基礎編》 # 第6章 モデル (Model)
  3. 現場で使える Django の教科書《基礎編》 # 第11章 データベースのマイグレーション