bong-u/til

Django - crud 기초

수정일 : 2024-06-26

개요

장고 프레임워크를 사용하여 기본적인 CRUD 기능과, REST API를 구현하는 방법을 알아보자.

프로젝트 구조

 1.
 2├── db.sqlite3
 3├── djtest (메인 앱)
 4│   ├── __init__.py
 5│   ├── asgi.py
 6│   ├── settings.py
 7│   ├── urls.py
 8│   ├── views.py
 9│   └── wsgi.py
10├── manage.py
11├── paste (생성한 앱)
12│   ├── __init__.py
13│   ├── admin.py
14│   ├── apps.py
15│   ├── migrations
16│   ├── models.py
17│   ├── serializers.py
18│   ├── tests.py
19│   ├── urls.py
20│   └── views.py
21└── requirements.txt

자주 쓰는 명령어

 1# 새로운 Django 프로젝트를 생성
 2python manage.py startproject
 3# 새로운 Django 앱을 생성
 4python manage.py startapp
 5# 데이터베이스에 적용할 마이그레이션 파일을 생성
 6python manage.py makemigrations
 7# 마이그레이션 파일을 실제 데이터베이스에 적용
 8python manage.py migrate
 9# 관리자(superuser) 계정을 생성
10python manage.py createsuperuser
11# 프로젝트의 테스트 케이스를 실행
12python manage.py test
13# 테스트용 서버를 특정 설정으로 실행
14python manage.py testserver

CRUD 구현

Paste Model 정의

 1from django.db import models
 2
 3class Paste(models.Model):
 4    title = models.CharField(max_length=100)
 5    content = models.TextField()
 6    # auto_now_add : 객체가 처음 생성될 때만 현재 날짜와 시간을 자동으로 설정
 7    created_at = models.DateTimeField(auto_now_add=True)
 8    # auto_now : 객체가 저장될 때마다 현재 날짜와 시간을 자동으로 설정
 9    updated_at = models.DateTimeField(auto_now=True)
10    class Meta:
11        ordering = ['-created_at']
12    def __str__(self):
13        return self.title

Paste Serializer 정의

1from rest_framework import serializers
2from .models import Paste
3
4class PasteSerializer(serializers.ModelSerializer):
5    class Meta:
6        model = Paste
7        fields = '__all__'
8        # 직접 지정하는 방법
9        # fields = ['title', 'content']

View 구현

  • PasteView
 1class PasteView(APIView):
 2    def get(self, _):
 3        pastes = Paste.objects.all()
 4        serializer = PasteSerializer(pastes, many=True)
 5        return Response(serializer.data, status=status.HTTP_200_OK)
 6
 7    def post(self, request):
 8        serializer = PasteSerializer(data=request.data)
 9        if serializer.is_valid():
10            serializer.save(user=request.user)
11            return Response(serializer.data, status=status.HTTP_201_CREATED)
12        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  • PasteDetailView
 1class PasteDetailView(APIView):
 2    def get(self, _, pk):
 3        try:
 4            paste = Paste.objects.get(pk=pk)
 5            serializer = PasteSerializer(paste)
 6            return Response(serializer.data, status=status.HTTP_200_OK)
 7        except Paste.DoesNotExist:
 8            return Response(status=status.HTTP_404_NOT_FOUND)
 9
10    def put(self, request, pk):
11        try:
12            paste = Paste.objects.get(pk=pk)
13        except Paste.DoesNotExist:
14            return Response(status=status.HTTP_404_NOT_FOUND)
15
16        if paste.user != request.user:
17            return Response(status=status.HTTP_403_FORBIDDEN)
18
19        serializer = PasteSerializer(paste, data=request.data)
20        if serializer.is_valid():
21            serializer.save()
22            return Response(serializer.data, status=status.HTTP_200_OK)
23        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
24
25    def delete(self, request, pk):
26        try:
27            paste = Paste.objects.get(pk=pk)
28        except Paste.DoesNotExist:
29            return Response(status=status.HTTP_404_NOT_FOUND)
30
31        paste.delete()
32        return Response(status=status.HTTP_204_NO_CONTENT)

urls.py

1from django.urls import path
2from paste.views import *
3
4urlpatterns = [
5    path('', PasteView.as_view(), name='paste_list_create'),
6    path('<int:pk>', PasteDetailView.as_view(), name='paste_get_update_delete'),
7]

Swagger 적용

PasteView

  • PasteView
 1class PasteView(APIView):
 2    @swagger_auto_schema(
 3        operation_description="Get list of pastes",
 4        operation_summary="Get list of pastes",
 5        responses={200: PasteSerializer(many=True)},
 6    )
 7    def get(self, _):
 8        ...
 9
10    @swagger_auto_schema(
11        operation_description="Create a new paste",
12        operation_summary="Create a new paste",
13        request_body=PasteSerializer,
14        responses={201: PasteSerializer, 400: "Bad Request"},
15    )
16    def post(self, request):
17        ...
  • PasteDetailView
 1class PasteDetailView(APIView):
 2    @swagger_auto_schema(
 3        operation_description="Get a paste by ID",
 4        operation_summary="Get a paste by ID",
 5        responses={200: PasteSerializer, 404: "Not Found"},
 6    )
 7    def get(self, _, pk):
 8        ...
 9
10    @swagger_auto_schema(
11        operation_description="Update a paste by ID",
12        operation_summary="Update a paste by ID",
13        request_body=PasteSerializer,
14        responses={
15            200: PasteSerializer,
16            400: "Bad Request",
17            403: "Forbidden",
18            404: "Not Found",
19        },
20    )
21    def put(self, request, pk):
22        ...
23
24    @swagger_auto_schema(
25        operation_description="Delete a paste by ID",
26        operation_summary="Delete a paste by ID",
27        responses={204: "No Content", 404: "Not Found"},
28    )
29    def delete(self, request, pk):
30        ...

swagger 적용 결과

swagger