ssung_데이터 엔지니어링/3주차_장고 활용한 API 서버 만들기

Django 활용하기(5)

ssungcohol 2023. 11. 3. 17:03

RelatedField

  • question과 user 사이의 관계를 매핑해주는 다양한 방법 존재
# polls_api/serializers.py

class UserSerializer(serializers.ModelSerializer):
    # pk id로 표시
    questions = serializers.PrimaryKeyRelatedField(many=True, queryset=Question.objects.all())
    
    # model.py에 __str__ 메소드에 정의된 내용을 표시
    questions = serializers.StringRelatedField(many=True, read_only=True)
    
    # model.py의 Question 내부의 특정 필드를 지정할 수 있음
    questions = serializers.SlugRelatedField(many=True, read_only=True, slug_field='pub_date')
    
    # model.py의 Question에 내용을 볼 수 있게 링크를 사용하여 연결
    questions = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='question-detail')
  • Choice를 불러올 때 model.py의 Choice class의 question에 related_name을 related_name = 'choices'로 설정

로그인을 한 사용자만 투표를 가능할 수 있게 수정

  • Django shell 사용
# 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')
        ]
        
# ========================================

# 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()
        
# =========================================

# Django Shell

>>> from polls.models import *
>>> question = Question.objects.first()
>>> choice = question.choices.first()
>>> from django.contrib.auth.models import User
>>> user= User.objects.get(username='luke')
>>> Vote.objects.create(voter=user,question=question,choice=choice)
<Vote: Vote object (1)>
>>> question.id
1

로그인을 한 사용자만 투표를 가능할 수 있게 수정

  • serializer & view로 구현
# polls_api/serializers.py

from polls.models import Question,Choice, Vote

class VoteSerializer(serializers.ModelSerializer):    
    voter = serializers.ReadOnlyField(source='voter.username')
        
    class Meta:
        model = Vote
        fields = ['id', 'question', 'choice', 'voter']
        
# =======================================

# polls_api/views.py

from polls.models import Question,Choice, Vote
from polls_api.serializers import VoteSerializer
from .permissions import IsOwnerOrReadOnly , IsVoter

class VoteList(generics.ListCreateAPIView):
    serializer_class = VoteSerializer
    permission_classes = [permissions.IsAuthenticated]
    
    def get_queryset(self, *args, **kwargs):
        return Vote.objects.filter(voter=self.request.user)
   
    def perform_create(self, serializer):
        serializer.save(voter=self.request.user)
  
class VoteDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Vote.objects.all()
    serializer_class = VoteSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsVoter]
    
# =======================================

# polls_api/permissions.py

class IsVoterOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        return obj.voter == request.user
        
# =======================================

# polls_api/urls.py

from django.urls import path, include
from .views import VoteList, VoteDetail

urlpatterns = [
    ...
    path('vote/', VoteList.as_view()),
    path('vote/<int:pk>/', VoteDetail.as_view()),
]
728x90

'ssung_데이터 엔지니어링 > 3주차_장고 활용한 API 서버 만들기' 카테고리의 다른 글

Django 활용하기(4)  (1) 2023.11.02
Django 활용하기(3)  (0) 2023.11.01
Django 활용하기(2)  (0) 2023.10.31
Django 활용하기(1)  (0) 2023.10.30