본문 바로가기
스파르타코딩 AI웹개발 3기

내일배움캠프_TIL_2022.12.05

by 청귤에이드 2022. 12. 6.

최종프로젝트에서 마이페이지에 해당하는 로직을 작성해보았는데, 

# workshops/serializers.py
class WorkshopListSerializer(serializers.ModelSerializer): # 워크샵 전체 목록 조회
    category = serializers.SerializerMethodField()
    location = serializers.SerializerMethodField()

    def get_category(self, obj):
        return obj.category.category

    def get_location(self, obj):
        return obj.location.district

    class Meta:
        model = Workshop
        fields = ('title', 'content', 'workshop_image', 'category', 'location',)


class WorkshopSerializer(serializers.ModelSerializer): # 특정 워크샵 상세 조회
    host = serializers.SerializerMethodField()
    likes_count = serializers.SerializerMethodField()
    participant_count = serializers.SerializerMethodField()
    category = serializers.SerializerMethodField()
    location = serializers.SerializerMethodField()
    review_workshop = ReviewSerializer(many=True)

    def get_host(self, obj):
        return obj.host.nickname

    def get_category(self, obj):
        return obj.category.category

    def get_location(self, obj):
        return obj.location.district
  
    def get_likes_count(self, obj):
        return obj.likes.count()

    def get_participant_count(self, obj):
        return obj.participant.count()

    class Meta:
        model = Workshop
        fields = ('title', 'content', 'workshop_image', 'category', 'location', 'address', 'host', 'amount', 'date', 'created_at', 'max_client', 'participant_count', 'likes_count', 'review_workshop',)


class SelectedHobbySerializer(serializers.ModelSerializer): # 마이페이지 - 내가 선택한 취미
    hobby = serializers.StringRelatedField(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',)  # (이후 변경 예정)

마이페이지에 해당하는 아래 세 개의 클래스는 기본적으로 User 모델을 기반으로 하되, 불러오고자 하는 데이터의 내용을 일부 인스턴스로 추가한 점을 확인할 수 있다.(hobby, member, workshop_host)

 

여기서 조금 주의할 점은, 첫번째 "내가 선택한 취미"에서 hobby는 'workshops.Hobby' 모델과 M:M 관계로 연결되어 있어 역참조로 헷갈릴 수 있으나, Hobby에 User 모델과 연결된 Foreignkey가 없기 때문에 정참조의 관계로 볼 수 있다.

(이 단순한 것을 몰라 몇시간을 머리 싸맨게 좀 허무했다. 이걸 계기로 데이터베이스에 대해 제대로 공부해야 할 필요성을 절감했고 다행히 친절한 팀원분들이 잘 설명해 주셔서 그나마 이해한 것 같다.)

 

따라서 related_name 없이 hobby라고 명명해주면 되지만, 아래 두 클래스(신청워크샵, 생성워크샵)의 경우 User모델을 기반으로 하지만 workshopListSerializser를 활용하고 그 안에 Workshop 모델이 적용되므로, 우선 User와 Workshop 의 상관관계를 파악해야 한다. User: Workshop = 1:M 이므로 Workshop 모델을 User 모델로 가져오기 위해서는 반드시 역참조 방식을 활용해야 하며 그 중 한 예로 related_name을 적어주면 된다. (아래 workshops/models.py 참고)

 

# 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 



class Review(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='reveiw_user')
    workshop = models.ForeignKey(Workshop, on_delete=models.CASCADE, related_name='review_workshop')
    content = models.TextField(max_length=50)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.content)

 

User 모델에 대한 정보는 아래와 같다.

# users/models.py

# 사용자모델 
class User(AbstractBaseUser):
    email = models.EmailField("이메일" , max_length=255, unique=True) 
    nickname = models.CharField("닉네임", max_length=15, unique=True)
    hobby = models.ManyToManyField('workshops.Hobby')
    profile_image = models.ImageField(blank=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['nickname']

    def __str__(self):
        return self.email 

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin