drf 정참조 역참조 개념이 아직도 헷갈려서 자료를 수집하고 있는 중인데
'분명 맞는 것 같은데 100% 확신하기는 어려움' 으로 정리할 수 밖에 없어서 이후에 개념이 더 명확해 지면 다시 정리하려고 합니다.
# workshops/serializers.py
class HobbySerializer(serializers.ModelSerializer):
class Meta:
model = Hobby
fields = '__all__'
class SelectedHobbySerializer(serializers.ModelSerializer): # 마이페이지 - 내가 선택한 취미
# hobby = serializers.StringRelatedField(many=True) # pk값 제외하고 string 데이터만 불러올때
# category = HobbySerializer(many=True) # 틀린 예
hobby = HobbySerializer(many=True)
class Meta:
model = User
fields = ('hobby',)
class AppliedWorkshopSerializer(serializers.ModelSerializer): # 마이페이지 - 신청 워크샵
member = WorkshopListSerializer(many=True)
class Meta:
model = User
fields = ('member',) # (이후 변경 예정)
class CreatedWorkshopSerializer(serializers.ModelSerializer): # 마이페이지 - 생성 워크샵
workshop_host = WorkshopListSerializer(many=True)
class Meta:
model = User
fields = ('workshop_host',) # (이후 변경 예정)
두 번째 'SelectedHobbySerializer'에서는 User 모델을 기반으로 하지만, 'hobby'에 대한 정보를 출력하고자 하기 때문에 fileds에 'hobby'를 추가하였고, HobbySerializer를 통해 'Hobby'모델을 사용하는 것을 알 수 있습니다. Hobby 모델에서는 User모델과 연결된 변수가 없기 때문에 정참조 관계이고, 정참조 시 타 모델을 가져올땐 모델명(소문자)로 기입하므로 Hobby의 소문자인 hobby로 반드시 명명해야 합니다.
hobby 위에 주석 처리된 #hobby와 #category에 대해 살펴보면, #hobby는 맞는 예지만 pk 값 없이 string 데이터만 필요할 때, StringRelatedField를 사용한 것이고, #category는 정참조의 경우는 처음에 Hobby 모델 안에 있는 변수명을 기입해야 하는 것으로 잘못 이해했어서 시간을 많이 허비했는데 반드시 유의하고 넘어가야할 부분이라 생각해서 적어봤습니다.
세번째 AppliedWorkshopSerializer와 CreatedWorkshopSerializer에서는 변수명을 각각 member, workshop_host라고 표기한 것을 볼 수 있는데, 이는 Workshop 모델을 바탕으로 한 serializer이기 때문에 User와 역참조 관계에 있는 Workshop모델의 변수를 가져오기 위해서 related_name 을 사용한 것입니다.
역참조 시, related_name 없이 디폴트로 '(모델명 소문자)_set' 로 표시해도 되지만 여기서 주의할 점은, '(모델명 소문자)_set'을 사용하기 위해서는 User모델과 Workshop 모델에 연결된 Foreignkey가 1개만 있어야 합니다. (사실 이 부분이 좀 명확하지 않지만 이것말고는 설명할 수 있는 원인이 없어서.. 이후에 다시 정확하게 정리하겠습니다) 실제로 member 대신 workshop_set를 적어서 테스트 해보면 속성값 오류가 나오는 것을 확인할 수 있습니다.
아래는 workshops앱에 있는 모델입니다.
# workshops/models.py
class Hobby(models.Model):
category = models.CharField(max_length=10)
def __str__(self):
return str(self.category)
class Location(models.Model):
district = models.CharField(max_length=20)
def __str__(self):
return str(self.district)
class Workshop(models.Model):
category = models.ForeignKey(Hobby, on_delete=models.CASCADE, related_name='workshop_category')
host = models.ForeignKey(User, on_delete=models.CASCADE, related_name='workshop_host')
date = models.DateTimeField()
location = models.ForeignKey(Location, on_delete=models.CASCADE)
address = models.CharField(max_length=20)
title = models.CharField(max_length=20)
content = models.TextField(max_length=500)
workshop_image = models.ImageField(upload_to='workshop/')
max_client = models.IntegerField()
amount = models.DecimalField(decimal_places=0, max_digits=10000000000000000)
created_at = models.DateTimeField(auto_now_add=True)
participant = models.ManyToManyField(User, related_name='member', symmetrical=False, blank=True)
likes = models.ManyToManyField(User, related_name='workshop_likes')
def __str__(self):
return self.title'스파르타코딩 AI웹개발 3기' 카테고리의 다른 글
| 내일배움캠프_TIL_2022.12.09 (0) | 2022.12.17 |
|---|---|
| 내일배움캠프_TIL_2022.12.08 (0) | 2022.12.09 |
| 내일배움캠프_TIL_2022.12.06 (0) | 2022.12.07 |
| 내일배움캠프_WIL_2022.12.04 (0) | 2022.12.06 |
| 내일배움캠프_TIL_2022.12.05 (0) | 2022.12.06 |