중개 모델의 제한 사항
문서에서 제시한 제한사항은 아래와 같다.
1.중개 모델은 소스 모델(Group)에 대해서 무조건 딱 1개의 외래키를 포함해야한다.
2.중개 모델이 소스 모델(Group)에 대해서 2개 이상의 외래키를 포함할 경우, ManyToManyField.through_fields를 사용하여 장고가 관계에 사용해야하는 외래 키를 명시적으로 지정해야 한다
3.타겟 모델(Person)
에 대해서도 동일하게 1,2번이 적용된다.
1번은 아래와 같은 경우를 나타낸다.
xxxxxxxxxx
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE) # 소스모델에 대해서 1개의 외래키만 가짐
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
1번의 경우에는 위와 같이 코드를 짰을 때, 별 문제가 없다.
그러나, 2개 이상의 외래키가 되는 경우는 문제가 된다 2번의 경우이다.
xxxxxxxxxx
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE) # 소스 모델에 대한 외래키 1
sub_group = models.ForeignKey(
Group,
on_delete=models.CASCADE,
related_name="membership_sub_group",
) # 소스 모델에 대한 외래키 2
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
이 경우 makemigrations
했을 때, 아래와 같은 에러가 뜬다 - 문맥 상 Validation Error
라는게 어느 것을 말하는지 확실하지 않지만, 아마도 아래 에러를 말하는 것으로 추정된다.
xxxxxxxxxx
thkwon_lab.Group.members: (fields.E334) The model is used as an intermediate model by 'thkwon_lab.Group.members', but it has more than one foreign key from 'Group', which is ambiguous. You must specify which foreign key Django should use via the through_fields keyword argument.
HINT: If you want to create a recursive relationship, use ManyToManyField("self", through="Membership").
이 에러를 해결하기 위해서는 through_fields
를 지정해주어야 한다 2번은 이 문제를 해결하기 위한 방법이다.
xxxxxxxxxx
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Meta:
db_table = "person"
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through="Membership",
through_fields=("group", "person"), # through_fields 추가
)
def __str__(self):
return self.name
class Meta:
db_table = "group"
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
sub_group = models.ForeignKey(Group, on_delete=models.CASCADE, related_name="membership_sub_groups")
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
class Meta:
db_table = "membership"
여기서 주의할 점은 무조건 (소스모델에 대한 외래키 필드이름, 타겟모델에 대한 외래키 필드 이름)
의 순서로 써주어야 한다.
위와 같이 했을 때는 makemigration
이 정상적으로 잘되는 것을 확인할 수 있다.
FYI, 위의 문제는 타겟모델(Person
)에 대해서도 똑같이 적용된다. 즉 타겟 모델의 외래키가 2개 이상 일 때도 makemigration
시에 똑같은 에러가 발생하고 똑같이 through_fields
를 지정함으로써 해결해주어야한다.
'개발 > 장고' 카테고리의 다른 글
[Django] 다대다 관계에서 through, through_fields, through_defaults (1) | 2021.01.30 |
---|---|
[Django] 다대다 관계의 모델을 직접 활용해 보자 (0) | 2021.01.30 |
[해설과 함께 읽는 Django 문서] Models - 다 대 다 관계 (0) | 2021.01.29 |
[해설과 함께 읽는 Django 문서] Models - 다 대 일 관계 (0) | 2021.01.27 |
[해설과 함께 읽는 Django 문서] Models - Verbose Field 이름 (0) | 2021.01.24 |