0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

メモ〜OneToOneFieldの注意点

Posted at

今回のお題

今回は、djangoアプリのOneToOneFieldを用いた際に経験した落とし穴について書きます。

結論

以下のようなモデルがあったとします。

class School(models.Model):
  name = models.CharField(max_length=20)

class Teacher(models.Model):
  name = models.CharField(max_length=20)

class Club(models.Model):
  name = models.CharField(max_length=20)
  teacher = models.OneToOneField(Teacher, on_delete=models.PROTECT)

class Student(models.Model):
  name = models.CharField(max_length=20)
  school = models.ForeignKey(School, on_delete=models.PROTECT)
  clubs = models.ManyToManyField(Club)

モデルとして学校・生徒・クラブ活動・大学があります。

学校と生徒は1対多数、クラブと生徒は多数対多数、クラブと教師は1対1で結びついています。

ここで、SchoolモデルとTeacherモデルにはレコードが一つずつあり(schoolとteacherとする)、それらに紐づいているstudentインスタンスとclubインスタンスは存在しないとします。

またそれとは別に部員0人のクラブ(clubとする)と帰宅部の生徒(student)が存在するとします。

この時

school.student_set.all()

これはエラーになりません。

同様に

if school.student_set.all():

これもfalseに分岐するだけです。

また多数対多数に関しても

club.student_set.all() #これはOK
if club.student_set.all() # これもfalseに分岐するだけ

となるので特に問題ありません。

逆パターンに関しても問題なしです。

student.clubs.all()
if student.clubs.all()

ですが1対1になると

teacher.club #これはエラー
if teacher.club: # これもflaseに分岐せずにエラーになる

関連するレコードが存在するのかを調べる方法としてhasattr関数が用意されているので、条件分岐処理の際にはこれを用いることになります。

if hasattr(teacher, "club"):
# これであればfalseに分岐する
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?