Django/DRF

DRF viewset을 이용한 serializers, authenticated 실습

UserDonghu 2023. 11. 20. 15:45

APIView -> Generic(APIView + Mixins) -> ViewSet(CRUD 다 가능. URL까지 DefaultRouter로 등록 권장)


실습

가상환경 설정

 

가상환경 활성화

 

django와 drf 설치

pip install django

pip install djangorestframework

 

startproject하고 blog 앱 생성

 

project / urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path('blog/', include('blog.urls')),
    path('api-auth/', include('rest_framework.urls')), # 웹 브라우저에서 로그인이 되게 해줌(test가 용이)
]

 

blog / urls.py 생성하고 urlpatterns = [] 추가

 

blog / models.py

from django.db import models
from django.conf import settings

class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

 

마이그레이션 하기

python manage.py makemigrations

python manage.py migrate

 

blog / serializers.py 

# form과 같은 형식
from rest_framework.serializers import ModelSerializer
from .models import Post
from django.contrib.auth import get_user_model


# class AuthorSerializer(ModelSerializer):
#     class Meta:
#         model = get_user_model()
#         fields = ['username', 'email']

class PostSerializer(ModelSerializer):
    # author = AuthorSerializer()
    class Meta:
        model = Post
        fields = [
            'id',
            'author',
            'title',
            'content',
            'created_at',
            'updated_at',
            # 'contents_len',
        ]

 

blog / views.py (viewset사용)

from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from .models import Post
from .serializers import PostSerializer

class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

 

viewset의 종류

  • viewsets.ReadOnlyModelViewSet(list, detail)
  • viewsets.ModelViewSet(list, create, detail, update, delete)

아래 모든 APIView 코드가 viewset 3줄로 해결

class BooksAPI(APIView):
    def get(self, request):
        books = Book.objecst.all()
        serializer = BookeSerializer(books, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        serializer = BookeSerializer(books, many=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    def delete(self, request):
        books = Book.objects.all()
        books.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class BookAPI(APIView):
    def get(self, request, id):
        book = get.object_or_404(Book, bid=id)
        serializer = BookSerializer(book)
        return Response(serializer.data, status=status.HTTP_200_OK)

 

blog / urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.register('post', views.PostViewSet)

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

 

runserver을 한 후, 테스트

 

postman이나 thunder client로도 테스트

 

인증 구현

settings.py

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.UserRateThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {
        'user': '1000/day', # 1000번의 요청을 하루에 할 수 있음
        # 비인증 요청 거부는 views.py에서 처리
    }
}

 

blog / views.py 수정

from rest_framework.viewsets import ModelViewSet
from .models import Post
from .serializers import PostSerializer
from rest_framework.permissions import IsAuthenticated
from .permissions import IsAuthorOrReadOnly

class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [IsAuthenticated, IsAuthorOrReadOnly] # 로그인된 사용자만 접근 가능, IsAuthorOrReadOnly 구현

 

blog / permissions.py 생성

from rest_framework import permissions

class IsAuthorOrReadOnly(permissions.BasePermission):
    # R은 모두 허용
    # C는 로그인 사용자만 허용
    # UD는 작성자만 허용
    def has_permission(self, request, view):
        '''
        GET, HEAD, OPTIONS 요청은 인증 여부와 상관없이
        항상 True를 리턴
        '''
        # if request.method in permissions.SAFE_METHODS:
        #     return True
        if request.user and request.user.is_authenticated:
            return True
        
    def has_object_permission(self, request, view, obj):
        '''
        GET, HEAD, OPTIONS 요청은 인증 여부와 상관없이
        항상 True를 리턴. 그 외 요청(PUT, DELETE)에 대해서는
        작성자에 한해서만 True를 리턴
        '''
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user

 

'Django > DRF' 카테고리의 다른 글

Django 프로젝트(3) - 📖 School Talks  (2) 2024.01.03
Django 프로젝트(2) - 🎓 AI 지식인 서비스  (0) 2023.12.02
JWT (JSON Web Token)  (0) 2023.11.17
DRF CBV와 User토큰  (0) 2023.10.20
DRF 와 마이크로서비스 튜토리얼  (1) 2023.10.18