파이썬

 

1. 모델(Model) 생성

먼저 사용할 모델을 생성합니다.

 

from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    author = models.CharField(max_length=50)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

 

마이그레이션 실행:

python manage.py makemigrations
python manage.py migrate

 

 

 

 

2. Serializer 생성

Serializer는 Article 모델을 JSON으로 변환하는 역할을 합니다.

from rest_framework import serializers
from .models import Article

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'  # 모든 필드 포함

 

 

3. ViewSet 구현

ViewSet을 사용하면 RESTful API의 CRUD 기능을 쉽게 관리할 수 있습니다.

from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()  # 모든 데이터 조회
    serializer_class = ArticleSerializer  # 직렬화 클래스 지정

ModelViewSet은 list, retrieve, create, update, destroy 기능을 자동으로 제공합니다.

 

 

4. URL 라우터 설정

ViewSet을 사용하면 router를 활용하여 URL을 자동으로 생성할 수 있습니다.

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

# DRF의 DefaultRouter 사용
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)  # 'articles/' 경로로 API 등록

urlpatterns = [
    path('', include(router.urls)),  # ViewSet 자동 URL 설정
]

 

이제 API 엔드포인트가 자동으로 생성됩니다.

 

 

 

5. API 테스트

서버 실행 후, 브라우저 또는 Postman에서 API를 테스트할 수 있습니다.

 

python manage.py runserver

 

1.목록 조회 (GET)

  • http://127.0.0.1:8000/articles/ 요청
  • 응답 예시:
[
    {
        "id": 1,
        "title": "첫 번째 글",
        "content": "DRF ViewSet 예제",
        "author": "홍길동",
        "created_at": "2024-02-18T12:00:00Z"
    }
]

 

2.상세 조회 (GET)

  • http://127.0.0.1:8000/articles/1/ 요청

 

 

3.새로운 게시글 등록 (POST)

  • http://127.0.0.1:8000/articles/ 요청 (Body에 JSON 데이터 전송)
{
    "title": "새로운 글",
    "content": "ViewSet을 이용한 DRF API",
    "author": "김철수"
}

 

 

4.게시글 수정 (PUT)

  • http://127.0.0.1:8000/articles/1/ 요청 (Body에 변경할 데이터 포함)
{
    "title": "수정된 제목",
    "content": "내용 업데이트",
    "author": "김철수"
}

 

5.게시글 삭제 (DELETE)

  • http://127.0.0.1:8000/articles/1/ 요청

 

 

6.정리

Django Rest Framework(DRF)의 ViewSet을 사용하면 CRUD 기능을 쉽게 구현할 수 있다.
DefaultRouter를 사용하면 URL 라우팅이 자동으로 생성된다.
테스트를 위해 Django 서버를 실행하고 Postman 또는 브라우저에서 API 요청을 확인할 수 있

 

 

 

 

 

7.왜 ModelViewSet 하나로 CRUD가 가능한가?

ModelViewSet은 DRF에서 제공하는 viewsets.ViewSet을 확장한 클래스입니다.
내부적으로 list, retrieve, create, update, destroy 메서드를 자동으로 포함하고 있기 때문에, 별도의 메서드 정의 없이 CRUD 기능이 동작합니다.

from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()  # 모든 데이터 조회
    serializer_class = ArticleSerializer  # 직렬화 클래스 지정

 

 

자동 생성되는 API 엔드포인트

router.register(r'articles', ArticleViewSet)을 사용하면 아래와 같은 RESTful API 엔드포인트가 자동 생성됩니다.

 

 

 

직접 ViewSet 메서드를 오버라이드해서 커스텀할 수도 있음

만약 특정 기능을 수정하고 싶다면, 개별 메서드를 오버라이드할 수도 있습니다.

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    # GET /articles/ 요청 시 호출 (목록 조회)
    def list(self, request, *args, **kwargs):
        print("목록 조회 요청이 들어왔습니다.")  # 로그 출력
        return super().list(request, *args, **kwargs)

    # POST /articles/ 요청 시 호출 (생성)
    def create(self, request, *args, **kwargs):
        print("새로운 게시글을 생성합니다.")  # 로그 출력
        return super().create(request, *args, **kwargs)

 

 

 

정리

ModelViewSet을 사용하면 기본적인 CRUD 기능이 자동으로 제공된다.
router.register()를 활용하면 별도의 URL 설정 없이 RESTful API가 자동 생성된다.
메서드를 직접 오버라이드하여 커스텀할 수도 있다.

DRF에서 ViewSet을 사용하는 이유가 바로 간결한 코드로 CRUD를 쉽게 구현할 수 있기 때문이에요!

 

 

 

 

 

 

8. 페이징 처리(Pagination)

 

페이징 처리를 하면 API 응답에서 한 번에 너무 많은 데이터를 불러오는 것을 방지할 수 있어요.

 

1) 전역 설정으로 페이징 적용 (settings.py)

settings.py에서 DEFAULT_PAGINATION_CLASS를 설정하면 모든 ViewSet에서 기본적으로 페이징이 적용됩니다.

 

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,  # 한 페이지에 10개씩
}

 

이렇게 설정하면 API 응답이 아래처럼 바뀝니다.

{
    "count": 100,
    "next": "http://127.0.0.1:8000/articles/?page=2",
    "previous": null,
    "results": [
        {
            "id": 1,
            "title": "첫 번째 글",
            "content": "DRF ViewSet 예제",
            "author": "홍길동",
            "created_at": "2024-02-18T12:00:00Z"
        },
        ...
    ]
}

 

2) 특정 ViewSet에서 페이징 적용

개별 ViewSet에서 페이징을 적용하려면 pagination_class를 설정하면 됩니다.

from rest_framework.pagination import PageNumberPagination
from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

# 커스텀 페이징 클래스 (옵션)
class CustomPagination(PageNumberPagination):
    page_size = 5  # 한 페이지에 5개씩
    page_size_query_param = 'size'  # URL에서 ?size=10 지정 가능
    max_page_size = 50  # 최대 50개까지 허용

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    pagination_class = CustomPagination  # 커스텀 페이징 적용

 

 

 

 

 

9. 검색 기능 추가 (Filtering & Search)

 

DRF의 filters를 이용하면 특정 필드에 대한 검색이 가능해요.

1) search_fields를 활용한 간단한 검색

rest_framework.filters.SearchFilter를 사용하면 특정 필드에서 검색할 수 있습니다.

from rest_framework import viewsets, filters
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    pagination_class = CustomPagination

    # 검색 필터 추가
    filter_backends = [filters.SearchFilter]
    search_fields = ['title', 'content', 'author']  # 검색할 필드 지정

 

➡ 이제 http://127.0.0.1:8000/articles/?search=DRF 로 요청하면
제목(title), 내용(content), 작성자(author)에서 "DRF"라는 단어가 포함된 데이터만 검색됩니다.

 

2) 필터링 (특정 필드 값으로 검색)

검색이 아니라 특정 값으로 필터링하려면 DjangoFilterBackend를 사용하면 돼요.

 

Django Filter 설치

pip install django-filter

 

settings.py 설정

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}

 

ViewSet에서 필터링 적용

from django_filters.rest_framework import DjangoFilterBackend

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    pagination_class = CustomPagination

    # 필터 추가
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['author', 'created_at']  # 특정 필드 값으로 필터링

➡ http://127.0.0.1:8000/articles/?author=홍길동 이렇게 요청하면
작성자가 "홍길동"인 글만 조회할 수 있어요.

 

 

 

 

10. 페이징 + 검색 + 필터링 같이 적용하기

 

위에서 설명한 페이징, 검색, 필터링을 동시에 적용하는 최종 코드입니다.

from rest_framework import viewsets, filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.pagination import PageNumberPagination
from .models import Article
from .serializers import ArticleSerializer

class CustomPagination(PageNumberPagination):
    page_size = 5
    page_size_query_param = 'size'
    max_page_size = 50

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    pagination_class = CustomPagination  # 페이징 설정

    filter_backends = [DjangoFilterBackend, filters.SearchFilter]  # 검색 & 필터 적용
    filterset_fields = ['author', 'created_at']  # 필터 가능 필드
    search_fields = ['title', 'content', 'author']  # 검색 가능 필드

 

➡ ✅ 이제 아래 API 요청을 할 수 있습니다.

 API 요청 예시

 

 

 

정리

페이징 (Pagination)

  • PageNumberPagination을 사용해 한 번에 가져오는 데이터 개수를 조절
  • page와 size 값을 URL에서 조절 가능

검색 (Search)

  • search_fields를 활용하면 특정 필드에서 부분 검색 가능
  • filters.SearchFilter를 적용하면 ?search=키워드로 검색 가능

필터링 (Filtering)

  • DjangoFilterBackend를 활용하면 특정 필드 값을 기준으로 검색 가능
  • filterset_fields = ['author', 'created_at'] 설정 후 ?author=홍길동 이런 방식으로 필터링 가능

 

 

 

 

 

 

11.일반적인 Django 프로젝트에서 Django REST framework(DRF) 인증 및 권한 설정

 

1. DRF 인증 및 권한 기본 설정 (settings.py)

기본적으로 DRF는 세션 인증을 사용하지만, 추가적으로 토큰 인증 또는 JWT 인증을 설정할 수 있습니다.

# settings.py

INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework.authtoken',  # DRF 토큰 인증을 사용하려면 추가
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',  # Django 기본 세션 인증
        'rest_framework.authentication.TokenAuthentication',  # DRF 토큰 인증
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',  # 인증된 사용자만 API 접근 가능
    ],
}

 

설명

  • SessionAuthentication → Django 기본 세션 기반 인증 (로그인 필요)
  • TokenAuthentication → REST API용 토큰 인증 (헤더에 Token <토큰값> 전달)
  • IsAuthenticated → 로그인된 사용자만 API 접근 가능 (비회원은 403 오류)

 

 

2. TokenAuthentication (토큰 인증) 추가 설정

DRF의 토큰 인증을 사용하려면 마이그레이션토큰 발급 과정이 필요합니다.

 

1) rest_framework.authtoken 설치 후 마이그레이션

python manage.py migrate
 

 

2) 토큰 발급 (관리자 또는 특정 사용자)

python manage.py drf_create_token <username>

또는 Django shell에서 실행:

from rest_framework.authtoken.models import Token
from django.contrib.auth import get_user_model

User = get_user_model()
user = User.objects.get(username="admin")  # 특정 사용자 선택
token, created = Token.objects.get_or_create(user=user)
print(token.key)  # 발급된 토큰 출력

➡ 이후, 클라이언트에서 API 요청 시 Authorization 헤더에 토큰을 추가하면 인증됨

 

3. JWT 인증 (JSON Web Token) 설정

기본적으로 Django는 JWT를 지원하지 않으므로 djangorestframework-simplejwt를 설치해야 합니다.

1) JWT 패키지 설치

pip install djangorestframework-simplejwt

 

2) settings.py에서 JWT 설정

from datetime import timedelta

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',  # JWT 인증 추가
        'rest_framework.authentication.SessionAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

# JWT 설정
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(days=1),  # 액세스 토큰 유효기간 (1일)
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),  # 리프레시 토큰 유효기간 (7일)
    'AUTH_HEADER_TYPES': ('Bearer',),  # 요청 헤더에서 "Bearer <토큰>" 형태로 인증
}

 

3) JWT 토큰 발급 및 갱신 API 추가

from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from django.urls import path

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),  # 로그인 후 JWT 발급
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),  # 리프레시 토큰 갱신
]

 

➡ ✅ JWT 로그인 요청 예시

POST /api/token/
Content-Type: application/json

{
    "username": "admin",
    "password": "password123"
}

응답:

{
    "access": "액세스 토큰 값",
    "refresh": "리프레시 토큰 값"
}

➡ 이후 API 요청 시 Authorization: Bearer <토큰값> 헤더를 포함하면 인증됨.

 

4. 인증 없이 일부 API 허용 (AllowAny 권한 설정)

로그인하지 않아도 특정 API는 접근 가능하도록 설정하려면 AllowAny를 사용하면 됩니다.

from rest_framework.permissions import AllowAny
from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    # 로그인 없이 접근 가능하도록 설정
    def get_permissions(self):
        if self.action in ['list', 'retrieve']:  # 목록 조회 및 상세 조회는 공개
            return [AllowAny()]
        return super().get_permissions()

 

➡ ✅ 이렇게 하면 목록(list)과 상세조회(retrieve)는 인증 없이 가능
➡ 반면 등록(create), 수정(update), 삭제(destroy)는 로그인해야 가능

 

 

5. 관리자 페이지에서 토큰 직접 발급

Django 관리자(admin) 페이지에서 유저별로 토큰을 생성할 수도 있습니다.

1) admin.py에서 Token 모델 등록

from django.contrib import admin
from rest_framework.authtoken.models import Token

admin.site.register(Token)

 

➡ 이후 Django 관리자 페이지에서 사용자별 토큰을 직접 추가/수정 가능

 

정리

기본 설정 (settings.py)

  • SessionAuthentication: Django 기본 세션 인증
  • TokenAuthentication: REST API에서 토큰 기반 인증
  • JWTAuthentication: JWT 기반 인증 (추가 설치 필요)

TokenAuthentication 설정

  1. rest_framework.authtoken 설치 후 migrate
  2. drf_create_token <username> 또는 Shell에서 직접 토큰 생성
  3. API 요청 시 Authorization: Token <토큰값> 헤더 사용

JWT 인증 설정

  1. pip install djangorestframework-simplejwt
  2. settings.py에서 JWTAuthentication 추가
  3. /api/token/ 엔드포인트에서 로그인 후 JWT 발급
  4. API 요청 시 Authorization: Bearer <토큰값> 헤더 사용

일부 API를 비회원도 접근 가능하게 설정

  • AllowAny를 사용하여 특정 API에 대해서는 인증 없이 허용 가능

 

 

 

 

 

 

 

12. Django Cookiecutter에서 DRF 인증 및 권한 설정

 

Django Cookiecutter에서는 config/settings/base.py 파일을 열고 아래와 같이 설정하면 됩니다.

# config/settings/base.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',  # Django 세션 인증
        'rest_framework.authentication.TokenAuthentication',  # DRF 토큰 인증
        'rest_framework.authentication.BasicAuthentication',  # 기본 인증 추가 (옵션)
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',  # 인증된 사용자만 API 접근 가능
    ),
}

 

1. TokenAuthentication 사용하려면?

DRF의 Token 인증을 사용하려면 rest_framework.authtoken 앱을 활성화하고 마이그레이션을 해야 합니다.

1) INSTALLED_APPS에 rest_framework.authtoken 추가

# config/settings/base.py

INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework.authtoken',  # DRF Token 인증 추가
]

 

2) 마이그레이션 실행

python manage.py migrate

 

3) 사용자에게 토큰 발급

python manage.py drf_create_token <username>

또는 Django shell에서 직접 실행:

from rest_framework.authtoken.models import Token
from django.contrib.auth import get_user_model

User = get_user_model()
user = User.objects.get(username="admin")  # 특정 유저 선택
token, created = Token.objects.get_or_create(user=user)
print(token.key)  # 토큰 출력

 

 

 

 

2. JWT 인증을 추가하려면?

Cookiecutter Django는 기본적으로 JWT 인증을 지원하지 않으므로, 직접 djangorestframework-simplejwt를 설치해야 합니다.

1) djangorestframework-simplejwt 패키지 설치

pip install djangorestframework-simplejwt

 

2) JWT 설정 추가 (base.py)

from datetime import timedelta

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',  # JWT 인증 추가
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

# JWT 설정
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(days=1),  # 액세스 토큰 유효기간 (1일)
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),  # 리프레시 토큰 유효기간 (7일)
    'AUTH_HEADER_TYPES': ('Bearer',),
}

 

3) JWT 로그인/토큰 갱신 API 추가

from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from django.urls import path

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),  # 로그인 후 JWT 발급
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),  # 리프레시 토큰 갱신
]

➡ 이제 POST /api/token/ 요청 시 access와 refresh 토큰을 받을 수 있습니다.

 

정리

1️⃣ SessionAuthentication + TokenAuthentication  base.py에서 설정
2️⃣ TokenAuthentication 사용 시 rest_framework.authtoken 추가 후 마이그레이션
3️⃣ JWT 인증 사용 시 djangorestframework-simplejwt 패키지 설치 및 설정
4️⃣ DEFAULT_PERMISSION_CLASSES를 IsAuthenticated로 설정하면 로그인한 사용자만 API 사용 가능

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

부모가 나를 완전하게 낳아 주셨다. 자식된 나도 그 몸을 완전하게 보전하여 부모에게 되돌려 주어야 한다. 이것을 효도(孝道)라고 하는 것이다. 공자가 한 말. -소학

댓글 ( 0)

댓글 남기기

작성