dev course - DE/TIL

[데브코스] TIL 15일차

nani-jin 2024. 4. 16. 18:01

RelatedField

  • polls_api/serializers.py
from rest_framework import serializers
from polls.models import Question, Choice
from django.contrib.auth.models import User
from django.contrib.auth.password_validation import validate_password

# Choice에 대한 Serializer
class ChoiceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Choice
        fields = ['choice_text', 'votes']


class QuestionSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username') # owner를 고르지 못하고, 읽기만하게
    choices = ChoiceSerializer(many=True, read_only=True)
    class Meta:
        model = Question
        fields = ['id','question_text','pub_date','owner','choices']

class UserSerializer(serializers.ModelSerializer):
    # 내아이디로 불러올 수 있는 question을 명시해야함
    # PrimaryKeyRelatedField(출력이 pk값으로 표시됨)-> StringRelatedField(출력이 String으로 표시됨. __str__에 정의되어있는...)
    # SlugRelatedField(questions 내용에 있는 것 중 아무거나 정해서 표시할 수 있음)
    # HyperlinkedRelatedField(해당 url로 이동)
    questions = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='question-detail') # many=True : 리스트 형식으로 복수개
    
    class Meta:
        model = User
        fields = ['id','username','questions']
  • polls_api/urls.py
...
class Choice(models.Model):
    question = models.ForeignKey(Question, related_name='choices', on_delete=models.CASCADE) # choice_set 대신 choices로 불러오기 위해
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    
    def __str__(self):
        return f'[{self.question.question_text}] {self.choice_text}'

 

 

 

models - 투표(votes) 기능 구현

  • polls/model.py
class Vote(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice = models.ForeignKey(Choice, on_delete=models.CASCADE)
    voter = models.ForeignKey(User, on_delete=models.CASCADE)
    
    # 하나의 질문에 대해 한 사람당 한번만 투표가능하게
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['question','voter'], name='unique_voter_for_questions')
        ]
  • polls_api/serializers.py
class ChoiceSerializer(serializers.ModelSerializer):
    votes_count = serializers.SerializerMethodField() # SerializerMethodField : 메서드에 의해 값이 정의됨
    
    class Meta:
        model = Choice
        fields = ['choice_text','votes_count']
    
    def get_votes_count(self, obj):
        return obj.vote_set.count() # 별도의 Forienkey를 정의하지 않으면 _set으로 가져올 수 있음
  • shell

 

 

 

 

serializers & views - 투표(votes) 기능 구현

직접 vote을 누를 수 있게