Djangoのモデルで1対1の関係を作成する方法は2つあります。
- OneToOneFieldを使う
- ForeignKeyにunique=Trueを設定して使う
どちらの1対1の関係を作成できますが、リレーションの「逆」側の扱いが異なります。
今回は、OneToOneFieldとForeignKey(unique=True)の違いを解説します。
OneToOneField
例としてRestaurantクラスを作成します。RestaurantとUserクラスが1対1の関係です。
from django.db import models
from django.contrib.auth.models import User
class Restaurant(models.Model):
owner = models.OneToOneField(
User,
on_delete=models.CASCADE,
)
OneToOneFieldを使ったの場合、Userクラスのオブジェクトから、Restaurantクラスのオブジェクトに直接アクセスできます。
OneToOneFieldを書いたクラスのオブジェクトにアクセスするには、小文字に変換したクラス名を使います。(related_nameというキーワード引数で変更することも可能です。)
例えば下記の様に、user.restaurantとかけば、userオブジェクトと1対1の関係にあるRestaurantオブジェクトにアクセスできます。
user = User.objects.get(id=1)
restaurant = Restaurant(owner = user)
restaurant.save()
print(restaurant == user.restaurant) # True
OneToOneFieldの方を使った方がコードが明解になり、おすすめです。
ForeignKey
次は、ForeignKeyを使ってRestaurantクラスを作成した例です。
from django.db import models
from django.contrib.auth.models import User
class Restaurant(models.Model):
owner = models. ForeignKey(
User,
on_delete=models.CASCADE,
unique=True,
)
ForeignKeyを使った場合、UserクラスのオブジェクトからRestaurantクラスのオブジェクトにアクセスする場合は、classname_setを使います。
classnameには参照元のクラス名を小文字に変換した名前が入ります。上記の場合は、restaurant_setです。
user = User.objects.get(id=1)
restaurant = Restaurant(owner = user)
restaurant.save()
users_restaurants = user.restaurant_set.all()
print(restaurant == users_restaurants[0]) # True
unique=Trueを設定して1対1の関係にしても、参照先→参照元へのアクセスは1対多の時と同じです。
基本的には user.restaurant_set.all() の様に、関連するオブジェクトのクエリセットを取得した後、1つ目の要素にアクセスする書き方になります。
まとめ
OneToOneFieldとForeignKey(unique=True)の違いは、リレーションの「逆」側の扱いが異なることです。
OneToOneFieldの方を使った方がコードが明解になるのでおすすめです。
コメントを残す