Django DRF (Rset-framework)

Haks.·2025년 2월 7일
0

How to use

목록 보기
22/32

REST / API

RESTful API

REST

Representation State Transfer => 상태를 표현하는 전송

API

  • 로그인 할 때 => prfile/me => 응답을 받아옴
  • Application Porgramming Interface

REST API

  1. 행동을 HTTP Method(get/ post/ put/ patch/ delete)를 사용하여 표현한다.
  2. / 슬래시는 계층 관계를 나타낼때 사용
  3. 마지막 슬래시는 포함하지 않는다.
  4. Resource들은 명사를 사용한다.
  5. _보다 -을 권장한다.
  6. 소문자를 사용
  7. 파일 확장자를 포함하지 않음
  8. 응답은 JSON이 대세

SPA

Single Page Application

REST API 제작

# blog/views/api_views.py
from django.http import JsonResponse
from blog.models import Blog

@csrf_exempt
def blog_list(request):
    if request.method == 'GET':
        blogs = Blog.objects.all()

        data = {
            'blog_list': [{'id': blog.id, 'title': blog.title} for blog in blogs]
        }
        return JsonResponse(data, status=200)
    else:
        body = json.loads(request.body.decode('utf-8'))

        blog = Blog.objects.create(
            **body, # 딕셔너리를 위에 작성해놓으면 맞추숴 넣어짐
            author=User.objects.first()
        )

        data = {
            'id' : blog.id,
            'title' : blog.title,
            'content' : blog.content,
            'author' : blog.author.username
        }
        return JsonResponse(data, status=201) # 생성이기에 201 create

# blog/urls.py
app_name ='api'

urlpatterns = [
    path('', api_views.blog_list, name='blog_list'),
]

# config/urls.py
    path('api', include('blog.urls')),
  1. settings.py에 APPEND_SLASH = False 넣어주면 / 있고 없고 차이를 구분함
  2. postman 으로 GET http://localhost:8000/api 요청 보내면 빈리스트 잘나올것임 젤끝에 / 슬래쉬 붙이면 오류
  3. superuser 만들어서 리스트 넣어보기, admin.py 에 등록 -> admin 페이지가서 블로그 생성후 다시 포스트맨에 get 요청보내면 나올것임
  4. postman 으로 post 요청 보내보기

Django REST framework

Django REST Framework(DRF)는 Django에서 웹 API를 쉽게 구축할 수 있도록 도와주는 강력한 라이브러리입니다. DRF는 직렬화(Serialization), 뷰(View), 권한 부여(Authorization) 등의 기능을 제공하여 RESTful API 개발을 단순화합니다.

  1. django rest framwork 검색 -> installation -> poetry 사용 -> poetry add djangorestframework -> installed_app + 'rest_framework' 등록 -> permission 적용 아래와 같이 작성
# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
}
  1. example 와 같이 적용해보기
# blog/serializers.py
from django.contrib.auth import get_user_model
from rest_framework import serializers

User = get_user_model()

# Form과 비슷한 역할
# 리턴하는 항목들도 필드에 적은 항목들만 리턴하도록 설계되어 있음, 스키마의 역할도 하는
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User


# blog/views/api_views.py
from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
# viewsets: REST FRAMEWORK 의 특별한 기능
# ReadOnlyModelViewSet : List와 Detail의 API를 만들어줌
# ModelViewSet: : List, Detail, Put, Create, Delete, Fetch 가능


# blog/urls.py   
from django.urls import path, include
from rest_framework import routers

from blog.views import api_views

app_name ='api'

router = routers.DefaultRouter(trailing_slash=False) # trailing_slash = False 슬래쉬가 있는지 없는지 

router.register(r'users', api_views.UserViewSet, basename='user')
# prefix 에서 users 를 붙인것은 include에서 users 로 시작하라는 거와 같음 앞에 무조건 /api/users 라 한것임
# viewset이기에 사실 여러개의 페이지를 연결한 것임, 현재 list, detail 페이지
urlpatterns = [
    # path('', api_views.blog_list, name='blog_list'),
    path('',include(router.urls)),
]


# config/urls.py
urlpatterns = [
    # path('', api_views.blog_list, name='blog_list'),
    path('',include(router.urls)),
]
  1. 홈페이지 -> 튜토리얼, viewsets and router 들어가서 ReadOnlyViewSet, ModelViewSet 어떻게 설게되어 있나 확인 가능

Serializer

Serializer는 Django 모델 인스턴스를 JSON과 같은 데이터 포맷으로 변환하거나, JSON 데이터를 모델 인스턴스로 변환하는 데 사용됩니다. 즉, 데이터의 직렬화와 역직렬화를 담당합니다.

사용법

from rest_framework import serializers
from .models import MyModel

class MyModelSerializer(serializers.ModelSerializer):
	class Meta:
    	model = MyModel
        fields = '__all__'

ModelSerializer 주요 메서드

  • to_representation(instance): 모델 인스턴스를 JSON 데이터로 변환합니다.
  • create(validated_data): 유효한 데이터를 사용하여 모델 인스턴스를 생성합니다.
  • update(instance, validated_data): 기존 모델 인스턴스를 업데이트합니다.

Serializer 주요 메서드

  • validate(self, attrs): 요청으로부터 입력받은 값들에 대해서 검증을 수행하는 메서드입니다.

View(Generic Views, APIView, ViewSets)

APIView

APIView는 Django의 기본 View를 확장하여 RESTful API 엔드포인트를 생성할 수 있도록 해줍니다. APIView는 HTTP 메서드(GET, POST, PUT, DELETE 등)를 오버라이드하여 사용할 수 있습니다.

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class MyAPIView(APIView):
    def get(self, request):
        data = {"message": "Hello, World!"}
        return Response(data, status=status.HTTP_200_OK)

    def post(self, request):
        data = request.data
        return Response(data, status=status.HTTP_201_CREATED)

Generic Views

Generic Views는 CRUD 작업을 간단히 처리할 수 있도록 미리 정의된 클래스입니다. Generic Views를 사용하면 반복적인 코드 작성을 줄일 수 있습니다.

  • ListCreateAPIView: 목록 조회 및 새 객체 생성을 처리합니다.
    • 각각 필요에따라 List만 혹은 Create만 사용가능
  • RetrieveUpdateDestroyAPIView: 객체의 조회, 수정, 삭제를 처리합니다.
    • 각각 따로 사용 가능
from rest_framework import generics
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelListCreateView(generics.ListCreateAPIView):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

ViewSets

ViewSet은 관련된 여러 뷰 로직을 하나의 클래스에 결합한 것입니다. ModelViewSet, ReadOnlyModelViewSet과 같은 기본 ViewSet을 사용하면, 더욱 간결하게 API를 정의할 수 있습니다.

from rest_framework import viewsets
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

주요 개념

1. Router

Router는 URL과 ViewSet을 자동으로 연결해주는 기능을 합니다. 이를 통해 개발자는 URLConf를 일일이 작성할 필요 없이, ViewSet만으로 URL 매핑이 가능합니다.

from rest_framework.routers import DefaultRouter
from .views import MyModelViewSet

router = DefaultRouter()
router.register(r'mymodels', MyModelViewSet)

urlpatterns = [
    path('', include(router.urls)),
]

2. Permissions

Permissions는 API에 대한 접근 권한을 제어하는 기능입니다. 기본적으로 DRF는 다양한 권한 클래스를 제공하며, 이를 통해 API 접근을 제한할 수 있습니다.

  • IsAuthenticated: 인증된 사용자만 접근 가능
  • IsAdminUser: 관리자만 접근 가능
  • AllowAny: 누구나 접근 가능
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class MyAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({"message": "Authenticated!"})

3. Authentication

DRF는 다양한 인증 방식을 지원합니다. 기본적인 Session 인증, Token 인증 외에도 OAuth, JWT 등의 다양한 인증 방식을 사용할 수 있습니다.

from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView

class MyAPIView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response({"message": "Token authenticated!"})

4. Throttling

Throttling은 API 요청을 제한하는 기능입니다. 특정 시간 내에 요청할 수 있는 횟수를 제한하여 API 남용을 방지할 수 있습니다.

from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView

class MyAPIView(APIView):
    throttle_classes = [UserRateThrottle]

    def get(self, request):
        return Response({"message": "Throttled request!"})

🧑‍💻 ViewSet 만들어보기

# blog/serializers.py
class BlogSerializer(serializers.ModelSerializer):
    author = UserSerializer(many=False) # ForeignKey 연결된것 연결하는것 serialzer 로 해놓은것만 이렇게 사용가능
    # ✅ `many=False`: 1명의 사용자(User)만 연결되므로 `False` 설정 (ForeignKey 관계)
    # ✅ `UserSerializer`를 사용하여 author 필드에 대한 직렬화(Serialization) 수행
    # ✅ 이렇게 하면 API 응답에서 author의 ID만 반환되는 것이 아니라, UserSerializer에 정의된 필드까지 포함됨
    # 이렇게 쓰면 꼭 까먹지말고 views 에서 select_related 등록하기

    class Meta:
        model = Blog
        fields = ['title', 'content', 'author', 'published_at', 'created_at', 'updated_at']

# blog/views/api_views.py
class BlogViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Blog.objects.all().order_by('-date_joined').select_related('author')
    serializer_class = BlogSerializer

# blog/urls.py
router.register(r'blogs', api_views.BlogViewSet, basename='blog')

0개의 댓글

관련 채용 정보