20230428 TIL - django 프레임워크 (5)

ohyujeong·2023년 5월 1일
0

TIL

목록 보기
15/27
post-thumbnail

📖 오늘의 학습

  • django 프레임워크 : RelatedField, Validation, Testing

Model 활용

투표(vote)기능 구현하기

사용자 단위로 들어와서 투표할 수 있는 기능을 구현해본다. 한 사용자가 한 질문에 대해 한 번 투표할 수 있도록 한다.

Vote 모델 생성

UniqueConstraint 제약을 만들어서 한 질문에 대해 사용자가 한번의 투표만 할 수 있도록 한다.

polls/models.py
from django.contrib.auth.models import User

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')
        ]

모델을 생성했기 때문에 DB에 반영해줄 수 있도록 migration을 실행한다.

python manage.py makemigrations
python manage.py migrate

Vote 수를 가져오는 Method 필드 추가

SerializerMethodField() 를 사용하여 값이 메소드에 의해 결정되도록 하는 votes_count 필드를 추가한다.

polls_api/serializers.py
class ChoiceSerializer(serializers.ModelSerializer):
    votes_count = serializers.SerializerMethodField()
    
    class Meta:
        model = Choice
        fields = ['choice_text', 'votes_count']
        
    def get_votes_count(self, obj):
        return obj.vote_set.count()

RelatedField

Question 모델과 User 모델의 관계를 정의하는 필드에는 여러가지 유형이 있다. 어떤 RelatedField를 사용하는지에 따라 화면에 표시되는 방식이 달라진다.

PrimaryKeyRelatedField

대상 모델의 key 값을 출력한다.

questions = serializers.PrimaryKeyRelatedField(many=True, queryset=Question.objects.all())

StringRelatedField

대상 모델의 __str__() 메소드에 정의된 결과를 출력한다.

questions = serializers.StringRelatedField(many=True, read_only=True)

SlugRelatedField

대상 모델의 필드 중 원하는 필드의 값을 출력한다. slug_field 파라미터에 원하는 필드를 입력한다.

questions = serializers.SlugRelatedField(many=True, read_only=True, slug_field='pub_date')

HyperlinkedRelatedField

아래와 같이 링크가 있는 텍스트의 형태를 출력한다. view_nameurls.py 파일에 정의한 경로의 name 을 설정하면 해당 경로로 링크된다.

questions = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='question-detail')

Validation

현재까지 구현한 vote 기능은 한 사용자가 한 질문에 대해 중복으로 투표하는 것을 막지 못하고, 질문에 대한 정해져 있는 선택지가 아닐 경우에 이에 대해 에러를 발생시키지 못한다.

Testing

직접 테스트 해보거나 POSTMAN을 사용하여 테스트할 수 있지만 테스트 코드를 이용하여 테스트한다면 좀 더 빠르고 편리하게 테스트를 할 수 있다.

앱 폴더에 test.py 파일을 생성하고 테스트 코드를 작성한 후 아래의 명령어로 test를 실행한다.

python manage.py test

test_ 로 시작하는 메소드만 실행된다.

polls_api/test.py
from django.test import TestCase
from polls_api.serializers import QuestionSerializer

class QuestionSerializerTestCase(TestCase):
    def test_with_valid_data(self):
        serializer = QuestionSerializer(data={'question_text': 'abc'})
        self.assertEqual(serializer.is_valid(), True)
        new_question = serializer.save()
        self.assertIsNotNone(new_question.id)
        
    def test_with_invalid_data(self):
        serializer = QuestionSerializer(data={'question_text': ''})
        self.assertEqual(serializer.is_valid(), False)

📝 주요메모사항


😵 공부하면서 어려웠던 내용

profile
거친 돌이 다듬어져 조각이 되듯

0개의 댓글