DRF : Django REST Framework
Django를 기반으로 REST API 서버를 만들기 위한 라이브러리
모놀리식 : 여태까지 해온 방식으로 템플릿 문법을 써서 사용자에게 html, css, js코드를 주는 방법. API 명세표가 따로 필요없음. Server에서 렌더링을 다 해줌
- 장점 : 규모가 있지 않은 서비스의 경우 빠른 개발 가능, 소규모 팀인 경우 선택하기 좋음
- 단점 : 규모가 커질 경우 BE, FE의 역할이 혼재된다.
마이크로서비스 : Django서버와 FE서버를 별도로 운영하는것. 앞으로 DRF를 사용해서 마이크로식으로 구현해 볼 것이다.
- 장점 : 서버엔지니어와 프론트엔드개발자가 API 명세서로 소통할 수 있음
- 단점 : 소규모 프로젝트에서는 의사소통 비용이 올라감.
실습
Django프로젝트를 생성하고 blog앱을 만들고 settings.py에 추가한다.
라이브러리 설치
pip install djangorestframework
pip install django-cors-headers
settings.py 수정
INSTALLED_APPS = [
# ~ 생략
# django lib app
'rest_framework', # 추가
'corsheaders', # 추가
# custom app
'blog',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', #최상단 추가
# ~ 생략
]
CORS_ORIGIN_ALLOW_ALL=True # 추가
CORS_ALLOW_CREDENTIALS=True # 추가
tutorialdjango와 blog에 urls.py 각각 등록한 후, views.py 수정
blog / views.py
def postlist(request):
posts = [
{'title':'1', 'content':'111'},
{'title':'2', 'content':'222'},
{'title':'3', 'content':'333'},
]
return JsonResponse(posts, safe=False) # dict이외의 것을 받을 경우, safe=False
이렇게 Django서버에서 데이터를 보내고, 다른 별개의 FE서버에서 이 데이터를 받아서 페이지를 구성하는게 마이크로서비스다.
FE서버에서 Json데이터를 받아오는 html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
</head>
<body>
<div id="data"></div>
<script>
// fetch로 http://127.0.0.1:8000/blog/ 데이터 가져와서 출력
fetch('http://127.0.0.1:8000/blog/')
.then(response => response.json())
.then(data => {
console.log(data);
document.getElementById('data').innerHTML = data;
});
</script>
</body>
</html>
DRF 사용해보기
blog / views.py
from django.shortcuts import render
from .models import Post
from django.http import JsonResponse
# rest_framework 추가 후 추가된 코드
from rest_framework import viewsets, permissions, generics, status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view
# FBV 사용하는 방식
@api_view(['GET']) # GET 요청을 처리한다는 데코레이터. ['GET', 'POST']하면 둘 다 처리 가능
def postlist(request):
posts = [
{'title':'1', 'content':'111'},
{'title':'2', 'content':'222'},
{'title':'3', 'content':'333'},
]
serializer = posts # 직렬화 하는 단계. Python 기본 객체는 자동 직렬화 가능
return Response(serializer) # Response로 반환 되었을 때 데이터를 읽을 수도 있고, POST를 보낼 수도 있음
# CBV 사용하는 방식
class MyView(APIView):
def get(self, request):
posts = [
{'title':'1', 'content':'111'},
{'title':'2', 'content':'222'},
{'title':'3', 'content':'333'},
]
serializer = posts # 직렬화 하는 단계. Python 기본 객체는 자동 직렬화 가능
return Response(serializer) # Response로 반환 되었을 때 데이터를 읽을 수도 있고, POST를 보낼 수도 있음
postlist = MyView.as_view()
Serializer 클래스를 이용해서 직렬화 하기
blog / models.py 추가
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
head_image = models.ImageField(
upload_to='blog/images/%Y/%m/%d/', blank=True)
file_upload = models.FileField(
upload_to='blog/files/%Y/%m/%d/', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
def __str__(self):
return self.title
blog / serializers.py 추가
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer): # Post라는 모델을 직렬화 하겠다
class Meta:
model = Post
fields = '__all__'
blog / views.py 수정
from django.shortcuts import render
from .models import Post
from django.http import JsonResponse
# rest_framework 추가 후 추가된 코드
from rest_framework import viewsets, permissions, generics, status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view
from .serializers import PostSerializer
@api_view(['GET', 'POST'])
def postlist(request):
if request.method == 'GET': # GET 요청으로 DB 읽을 때
postlist = Post.objects.all()
serializer = PostSerializer(postlist, many=True) # postlist 직렬화. 다수의 Queryset을 넘길 때는 many=True
return Response(serializer.data)
elif request.method == 'POST': # POST 요청으로 DB에 추가할 때
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # 둘다 아니면 에러
CBV를 이용해서 구현한 postlist와 postdetail
from django.shortcuts import render
from .models import Post
from django.http import JsonResponse, Http404
# rest_framework 추가 후 추가된 코드
from rest_framework import viewsets, permissions, generics, status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view
from .serializers import PostSerializer
class PostList(APIView):
def get(self, request):
postlist = Post.objects.all()
serializer = PostSerializer(postlist, many=True)
return Response(serializer.data)
def post(self, request):
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class PostDetail(APIView):
def get(self, request, pk):
post = Post.objects.get(pk=pk)
serializer = PostSerializer(post)
return Response(serializer.data)
def get_object(self, pk):
try:
return Post.objects.get(pk=pk)
except Post.DoesNotExist:
raise Http404
def put(self, request, pk):
post = self.get_object(pk)
serializer = PostSerializer(post, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
post = self.get_object(pk)
post.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
postlist = PostList.as_view()
postdetail = PostDetail.as_view()
'Django > DRF' 카테고리의 다른 글
Django 프로젝트(3) - 📖 School Talks (2) | 2024.01.03 |
---|---|
Django 프로젝트(2) - 🎓 AI 지식인 서비스 (0) | 2023.12.02 |
DRF viewset을 이용한 serializers, authenticated 실습 (1) | 2023.11.20 |
JWT (JSON Web Token) (0) | 2023.11.17 |
DRF CBV와 User토큰 (0) | 2023.10.20 |