[Python] Django 투표 앱 RESTful api로 리팩토링하기

2024. 12. 17. 22:50·Language/Python

DetailView, IndexView, ResultsView

기존의 DetailView는 html 형태로 데이터를 리턴함

class DetailView(generic.DetailView):
    model = Question
    template_name = "polls/detail.html"

 

get 요청시 model로 필요한 데이터를 받아오고, json 형태로 변환하여 리턴하도록 DetailView를 변경

  • Question 테이블에 특정 id의 데이터가 없으면 404 error 발생하도록 처리
class DetailView(View):
    def get(self, request, pk):
        question_with_choice = get_object_or_404(Question.objects.prefetch_related('choice_set'), pk=pk)
        choices = list(question_with_choice.choice_set.all().values('id', 'choice_text'))

        question_dict = model_to_dict(question_with_choice)
        question_dict['polls_choice'] = choices

        response = json.dumps(question_dict, cls=DjangoJSONEncoder)
        return HttpResponse(response, content_type='application/json')

 

IndexView, ResultsView도 json 형태로 데이터를 리턴하도록 변경

class IndexView(View):
    def get(self, request):
        all_questions = Question.objects.all()
        data_list = []
        for obj in all_questions:
            data_list.append(model_to_dict(obj))

        response = json.dumps(data_list, cls=DjangoJSONEncoder)
        return HttpResponse(response, content_type='application/json')


class DetailView(View):
    def get(self, request, pk):
        question_with_choice = get_object_or_404(Question.objects.prefetch_related('choice_set'), pk=pk)
        choices = list(question_with_choice.choice_set.all().values('id', 'choice_text'))

        question_dict = model_to_dict(question_with_choice)
        question_dict['polls_choice'] = choices

        response = json.dumps(question_dict, cls=DjangoJSONEncoder)
        return HttpResponse(response, content_type='application/json')
    

class ResultsView(generic.DetailView):
    def get(self, request, pk):
        question_with_choice = get_object_or_404(Question.objects.prefetch_related('choice_set'), pk=pk)
        choices = list(question_with_choice.choice_set.all().values('id', 'choice_text', 'votes'))

        question_dict = model_to_dict(question_with_choice)
        question_dict['polls_choice'] = choices

        response = json.dumps(question_dict, cls=DjangoJSONEncoder)
        return HttpResponse(response, content_type='application/json')

 

vote

post 요청을 받으면, choice_id의 votes에 1을 추가하고 {"message": "voted"}를 리턴하도록 변경

@csrf_exempt
def vote(request, question_id):
    if request.method == 'POST':
        question = get_object_or_404(Question, pk=question_id)
        try:
            # { "choice_id": 1 }
            data = json.loads(request.body)
            selected_choice = question.choice_set.get(pk=data["choice_id"])
        except (KeyError, Choice.DoesNotExist, json.JSONDecodeError):
            return JsonResponse({"error": "Invalid choice"}, status=400)
        else:
            selected_choice.votes = F("votes") + 1
            selected_choice.save()
            return JsonResponse({"message": "voted"}, status=201)

 

choice_id를 4로 해서 post 요청을 하면, voted 메시지를 요청 받음

 

polls_choice 테이블 확인해보면, 선택한 id의 votes가 1 증가함

views.py 전체 코드

from django.db.models import F
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import View, generic
from django.core.serializers.json import DjangoJSONEncoder
from django.forms.models import model_to_dict
from django.views.decorators.csrf import csrf_exempt
import json

from .models import Choice, Question


class IndexView(View):
    def get(self, request):
        all_questions = Question.objects.all()
        data_list = []
        for obj in all_questions:
            data_list.append(model_to_dict(obj))

        response = json.dumps(data_list, cls=DjangoJSONEncoder)
        return HttpResponse(response, content_type='application/json')


class DetailView(View):
    def get(self, request, pk):
        question_with_choice = get_object_or_404(Question.objects.prefetch_related('choice_set'), pk=pk)
        choices = list(question_with_choice.choice_set.all().values('id', 'choice_text'))

        question_dict = model_to_dict(question_with_choice)
        question_dict['polls_choice'] = choices

        response = json.dumps(question_dict, cls=DjangoJSONEncoder)
        return HttpResponse(response, content_type='application/json')
    

class ResultsView(generic.DetailView):
    def get(self, request, pk):
        question_with_choice = get_object_or_404(Question.objects.prefetch_related('choice_set'), pk=pk)
        choices = list(question_with_choice.choice_set.all().values('id', 'choice_text', 'votes'))

        question_dict = model_to_dict(question_with_choice)
        question_dict['polls_choice'] = choices

        response = json.dumps(question_dict, cls=DjangoJSONEncoder)
        return HttpResponse(response, content_type='application/json')


@csrf_exempt
def vote(request, question_id):
    if request.method == 'POST':
        question = get_object_or_404(Question, pk=question_id)
        try:
            # { "choice_id": 1 }
            data = json.loads(request.body)
            selected_choice = question.choice_set.get(pk=data["choice_id"])
        except (KeyError, Choice.DoesNotExist, json.JSONDecodeError):
            return JsonResponse({"error": "Invalid choice"}, status=400)
        else:
            selected_choice.votes = F("votes") + 1
            selected_choice.save()
            return JsonResponse({"message": "voted"}, status=201)

 

응답 결과

IndexView

 

DetailView

 

ResultsView

 

'Language > Python' 카테고리의 다른 글

[Python] Django 투표 앱과 frontend 연결하기  (0) 2024.12.17
[Python] Django Model, View 사용하기  (0) 2024.12.17
[Python] Django 투표 앱 만들기 (2)  (0) 2024.12.17
[Python] Django 투표 앱 만들기 (1)  (1) 2024.12.17
[Python] Django 프로젝트 생성하기  (1) 2024.12.17
'Language/Python' 카테고리의 다른 글
  • [Python] Django 투표 앱과 frontend 연결하기
  • [Python] Django Model, View 사용하기
  • [Python] Django 투표 앱 만들기 (2)
  • [Python] Django 투표 앱 만들기 (1)
Doodo
Doodo
  • Doodo
    Doodo
    Doodo
  • 전체
    오늘
    어제
    • 분류 전체보기 (192)
      • CS (17)
        • Network (11)
        • Database (6)
      • Language (19)
        • Python (11)
        • SQL (6)
        • R (2)
      • Linux (17)
      • DevOps (35)
        • Git (7)
        • Docker (8)
        • Kubernetes (9)
        • GCP (4)
        • AWS (7)
      • Data Engineering (50)
        • 책 리뷰 (14)
        • Airflow (35)
        • Redis (1)
      • DBMS (21)
        • CUBRID (21)
      • ML & DL (2)
      • 코딩테스트 (24)
      • 프로젝트 (7)
        • 서울시 대기현황 데이터 적재 프로젝트 (4)
        • CryptoStream (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
Doodo
[Python] Django 투표 앱 RESTful api로 리팩토링하기
상단으로

티스토리툴바