DjangoのAbstract ModelとOneToOneField

Django

はじめに

DjangoのAbstract Modelを使って2個のモデルに継承を行い、個別にテーブルを作りたかったのでメモしておきます。

Abstract Modelから継承したモデルをOneToOneFieldでリレーションする場合、同じアプリと別のアプリから指定する記述方法が異なりました。

環境

- Django 5.0.3
- Python 3.10.13
- pipenv 2023.12.1

構成

- app
- app_child

- config
    - settings.py

- db.sqlite3
- manage.py

settings.py

appとapp_childを追加します。

INSTALLED_APPS = [
    --- 省略 ---

    'app',
    'app_child',
]

app/models.py

appのモデルを記述します。

from django.db import models
from django.contrib.auth import get_user_model

UserModel = get_user_model()

# abstractモデル
class ArticleBase(models.Model):
    class Meta:
        abstract = True

    user    = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    is_save = models.BooleanField(default=False)

# 継承
class Article(ArticleBase):
    title = models.CharField(max_length=256)

# 同じアプリ内のOneToOneField
class TestLocal(models.Model):
    name1 = models.OneToOneField('app.Article', on_delete=models.CASCADE, related_name='article11')
    name2 = models.OneToOneField('app.Article', on_delete=models.CASCADE, related_name='article12')

app_child/models.py

app_childのモデルを記述します。
別アプリから指定する場合は【アプリ名】.【モデル名】です。
今回は「app.Article」のように記述します。
「Article」と指定するとエラーになります。

from django.db import models

#from app.models import Article

# 別アプリのOneToOneField
class TestRemote(models.Model):
    name1 = models.OneToOneField('app.Article', on_delete=models.CASCADE, related_name='article21')
    name2 = models.OneToOneField('app.Article', on_delete=models.CASCADE, related_name='article22')

テスト

マイグレーションできるかテストします。

python manage.py makemigrations

結果です。

Migrations for 'app':
  app/migrations/0001_initial.py
    - Create model Article
    - Create model TestLocal

Migrations for 'app_child':
  app_child/migrations/0001_initial.py
    - Create model TestRemote

Comments