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 |