Python/Django

Django + PostgreSQL CRUD 만들기

요술공주밍키 2022. 2. 23. 11:14

저번 포스팅에서 Django와 PostgreSQL을 연동하는 과정을 거쳤으니 이번에는 직접 모델 정의하고

CRUD를 만들어보겠습니다.


 

Django Model 정의

만들어진 App 안에 Models.py에서 클래스를 추가한다.

from django.db import models

class Post(models.Model):
	title = models.CharField(max_length=70, blank=False, default='')
    	text = models.CharField(max_length=200,blank=False, default='')
    	published = models.BooleanField(default=False)
각자 자동으로 DB에 맵핑됩니다.

 

 

Serializer 클래스 생성

PostSerializer JSON에서 직렬화 및 역직렬화를 관리하는 클래스를 생성.

from rest_framework import serializers
from .models import Post

class PostListSerializer(serializers.ModelSerializer):
	class Meta:
    	model = Post
        fields = ('id', 'title', 'text', 'published')
Meta 클래스에서 2개의 속성을 선언
- model : Serializer용 모델
- fields : 직렬화에 포함될 필드 이름의 튜플

 

 

뷰 페이지에 대한 경로 정의

클라이언트가 HTTP 요청을 보낼 때 경로를 정의하여 응답하는 방법을 설정해야 합니다.

경로는 이렇게 설정하겠습니다.

  • /api/post : GET, POST, DELETE
  • /api/post/:id : GET, PUT, DELETE
  • /api/post/published : GET

 

views.py에 정의된 내용을 일치시켜줄 urls.py를 작성합니다.

from django.conf.urls import url 
from . import views 
 
urlpatterns = [ 
    url(r'^api/post$', views.post_list),
    url(r'^api/post/(?P<pk>[0-9]+)$', views.post_detail),
    url(r'^api/post/published$', views.post_list_published)
]
App 내부의 urls.py를 작성하였다면 루트 디렉터리의 urls.py에 include 하는 것을 잊으면 안 됩니다.
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('dragon_community.apps.post.urls')),
]

 

 

API 작성

CRUD 작업을 위하여 API를 작성합니다.

  • post_list : 튜토리얼 목록 GET, 새 튜토리얼 POST, 모든 튜토리얼 DELETE
  • post_detail : 특정 튜토리얼 GET, PUT, DELETE
  • post_list_published : 조건에 맞는 모든 튜토리얼 GET

 

만들어진 App 안에 views.py를 작성합니다.

from django.shortcuts import render
from django.http.response import JsonResponse
from rest_framework.parsers import JSONParser
from rest_framework import status
from .serializer import PostListSerializer
from .models import Post
from .serializer import PostListSerializer
from rest_framework.decorators import api_view


@api_view(['GET', 'POST', 'DELETE'])
def post_list(request):
    if request.method == 'GET':
        post = Post.objects.all()
        title = request.GET.get('title', None)
        if title is not None:
            post = post.filter(title__icontains=title)

        post_serializer = PostListSerializer(post, many=True)
        return JsonResponse(post_serializer.data, safe=False)
    elif request.method == 'POST':
        post_data = JSONParser().parse(request)
        post_serializer = PostListSerializer(data=post_data)
        if post_serializer.is_valid():
            post_serializer.save()
            return JsonResponse(post_serializer.data, status=status.HTTP_201_CREATED)
        return JsonResponse(post_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        count = Post.objects.all().delete()
        return JsonResponse({'message': '{} post were deleted successfully!'.format(count[0])}, status=status.HTTP_204_NO_CONTENT)


@api_view(['GET', 'PUT', 'DELETE'])
def post_detail(request, pk):
    # find post by pk (id)
    try:
        post = Post.objects.get(pk=pk)
    except Post.DoesNotExist:
        return JsonResponse({'message': 'The post does not exist'}, status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        post_serializer = PostListSerializer(post)
        return JsonResponse(post_serializer.data)
    elif request.method == 'PUT':
        post_data = JSONParser().parse(request)
        post_serializer = PostListSerializer(post, data=post_data)
        if post_serializer.is_valid():
            post_serializer.save()
            return JsonResponse(post_serializer.data)
        return JsonResponse(post_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        post.delete()
        return JsonResponse({'message': 'post was deleted successfully!'}, status=status.HTTP_204_NO_CONTENT)
        


@api_view(['GET'])
def post_list_published(request):
    post = Post.objects.filter(published=True)
    if request.method == 'GET':
        post_serializer = PostListSerializer(post, many=True)
        return JsonResponse(post_serializer.data, safe=False)

 

 

마이그레이션

python manage.py makemigrations post를 진행 한 뒤 python manage.py migrate post를 진행하게 되면

Operations to perform:
  Apply all migrations: post
Running migrations:
  Applying post.0001_post... OK

위 내용이 출력되고 DB를 확인하면 post 테이블이 생성되어 있을 것이다.

 

저 같은 경우 마이그레이션 과정 중 Model을 잘못 설정하고 마이그레이션을 해버려서 삭제를 한 뒤
다시 마이그레이션을 시도했는데 그때 Running migrations: no migrations to apply가 출력되었다.
구글링 해보니 프로젝트 내부뿐만 아니라 DB 내에서도 migration 테이블이 존재하는데 그곳에 이전에 했던 내역이
남아있어서 같은 이름의 마이그레이션이 적용되지 않았던 것
따라서 0002_post 형식으로 이름을 바꾼 뒤 migrate 해주니 문제없이 잘 적용되었습니다.

단순히 Django와 PostgreSQL을 연결하고 CRUD코드만 작성하여 실행시키면 될 줄 알았던 일이었는데

역시 계획처럼 되지 않았다. 덕분에 해당 내용과 다른 내용들도 알게 되고 공부하는 즐거움이 있었던 것 같다.