今回のお題
今回は、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に分岐する