Django RestAPI PostgreSQL

이번 글은 Django 프레임워크에서 PostgreSQL을 연동하여 API를 처음 만드는 개발자를 대상으로 빠르게 구현의 목적이 있습니다. 상세 설명이 필요하시다면 다른 곳을 참조 하시는걸 추천 드립니다.

설명이 부족하여 이해의 어려움이 있다면, Github 저장소에서 소스 전체를 확인 해보시면 도움이 될 것 입니다. (이번 글의 개발 환경은 macOS에서 진행 되었습니다.)

사전 준비 사항

CREATE SEQUENCE board_board_no_seq;

CREATE TABLE IF NOT EXISTS public.board
(
    board_no bigint NOT NULL DEFAULT nextval('board_board_no_seq'::regclass),
    title character varying(200) COLLATE pg_catalog."default" NOT NULL,
    contents text COLLATE pg_catalog."default" NOT NULL,
    writer character varying(50) COLLATE pg_catalog."default" NOT NULL,
    view_count integer NOT NULL,
    link_url character varying(200) COLLATE pg_catalog."default" NOT NULL,
    create_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT board_pkey PRIMARY KEY (board_no)
)

CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
  NEW.update_date = CURRENT_TIMESTAMP;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER board_update_timestamp_trigger
BEFORE UPDATE ON public.board
FOR EACH ROW
EXECUTE PROCEDURE update_timestamp();

Django 설치

터미널에서 “pip” 명령어로 django를 설치 합니다.

$ pip install django

django 설치가 완료 되었으면 “django rest framework”를 설치 합니다.

$ pip install djangorestframework

Django 프로젝트 생성

터미널에서 Django 프로젝트를 생성할 위치로 이동 후 “django-admin startproject” 명령어로 프로젝트를 생성 합니다.

$ django-admin startproject django_restapi

프로젝트가 생성 되었으면 프로젝트 디렉토리로 이동 후 “startapp” 명령어로 app을 생성 합니다.

$ cd django_restapi
$ python manage.py startapp restapi

django를 실행 합니다.

$ python manage.py runserver

브라우저에서 http://127.0.0.1:8000 으로 접속 합니다. 아래의 화면이 나오면 정상 실행 된 것 입니다.

django restapi pg 06

Hello World

VS Code로 “djangoapi/setting.py” 파일을 열어서 “INSTALLEDAPPS” 에 ‘restapi’, ‘rest_framework’ 를 추가 합니다.

django restapi pg 07

“restapi/views.py” 에 “restframework.response, restframework.decorators” 를 import 하고 “hello” 함수를 추가 합니다.

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view

# Create your views here.
@api_view(['GET'])
def hello(request):
    return Response("Hello World!")

django restapi pg 08

“restapi/urls.py” 파일을 생성 후 아래 코드를 추가 합니다.

from django.urls import path
from .views import *

urlpatterns = [
    path("hello/", hello),
]

django restapi pg 09

“django_api/urls.py”에서 “include”를 import하고, “urlpatterns”에 “api” url을 추가 합니다.

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('restapi.urls')),
]

django restapi pg 10

브라우저에서 http://127.0.0.1:8000/api/hello 접속을 확인 합니다.

django restapi pg 11

Database 설정

PostgreSQL 라이브러리를 설치 합니다. 터미널에서 “python -m pip install psycopg2-binary” 를 실행 합니다.

$ python -m pip install psycopg2-binary

“/django_api/settings.py” 파일에서 DATABASE에 DB 정보를 아래 형식으로 수정 합니다.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'DATABASE명',
        'USER': '계정',
        'PASSWORD': '비밀번호',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

Model을 생성 합니다. 터미널에서 inspectdb 명령어를 실행 합니다.

$ python manage.py inspectdb > restapi/models.py

실행이 완료되면 “restapi/models.py” 파일이 생성되고 아래와 같은 정보가 생성 됩니다.

django restapi pg 12

날짜를 DB에서 자동으로 입력하기 위해 Board에 “createdate” 에는 “autonowadd=True”, “updatedate” 에는 “auto_now=True” 를 추가 합니다.

from django.db import models


class Board(models.Model):
    board_no = models.BigAutoField(primary_key=True)
    title = models.CharField(max_length=200)
    contents = models.TextField()
    writer = models.CharField(max_length=50)
    view_count = models.IntegerField()
    link_url = models.CharField(max_length=200)
    create_date = models.DateTimeField(auto_now_add=True)
    update_date = models.DateTimeField(auto_now=True)

    class Meta:
        managed = False
        db_table = 'board'

변경된 모델을 적용하기 위해 migration을 한 후 재 실행 합니다.

$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver

모델의 데이터를 API로 전달하기 위해 “restapi/serializers.py” 파일을 생성 후 아래 정보를 입력 합니다.

from rest_framework import serializers
from .models import Board

class BoardSerializer(serializers.ModelSerializer):
    class Meta:
        model = Board
        fields = '__all__'

등록 API

“restapi/views.py” 파일에 “status, Board, BoardSerializer” 를 Import 한 후 “board_create” 함수를 추가 합니다.

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .models import Board
from .serializers import BoardSerializer

# Create your views here.
@api_view(['GET'])
def hello(request):
    return Response("Hello World!")


@api_view(['POST'])
def board_create(request):
    serializer = BoardSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

“restapi/urls.py” 파일의 “urlpatterns” 에 “board_create” 경로를 추가 합니다.

from django.urls import path
from .views import *

urlpatterns = [
    path("hello/", hello),
    path("board/create/", board_create),
]

POSTMAN에서 Body 값을 아래와 같이 JSON 형식으로 추가 후 POST 로 http://127.0.0.1:8000/api/board/create/ 실행 합니다.

{
  "title": "제목",
  "contents": "내용",
  "writer": "작성자",
  "view_count": 1,
  "link_url": "https://"
}

django restapi pg 13

목록조회 API

“/restapi/views.py” 파일에 “board_list” 함수를 추가 합니다.

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .models import Board
from .serializers import BoardSerializer

# Create your views here.
@api_view(['GET'])
def hello(request):
    return Response("Hello World!")


@api_view(['GET'])
def board_list(request):
    datas = Board.objects.all()
    serializer = BoardSerializer(datas, many=True)

    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['POST'])
def board_create(request):
    serializer = BoardSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

“restapi/urls.py” 파일의 “urlpatterns” 에 “board” 경로를 추가 합니다.

from django.urls import path
from .views import *

urlpatterns = [
    path("hello/", hello),
    path("board/", board_list),
    path("board/create/", board_create),
]

POSTMAN에서 GET으로 http://127.0.0.1:8000/api/board 실행 합니다.

django restapi pg 14

조회 API

“restapi/views.py” 파일에 “board” 함수를 추가 합니다.

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .models import Board
from .serializers import BoardSerializer

# Create your views here.
@api_view(['GET'])
def hello(request):
    return Response("Hello World!")


@api_view(['GET'])
def board_list(request):
    datas = Board.objects.all()
    serializer = BoardSerializer(datas, many=True)

    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['GET'])
def board(request, board_no):
    datas = Board.objects.filter(board_no=board_no)
    serializer = BoardSerializer(datas, many=True)

    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['POST'])
def board_create(request):
    serializer = BoardSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

“restapi\urls.py” 파일의 “urlpatterns” 에 “board/<int:board_no>” 경로를 추가 합니다.

from django.urls import path
from .views import *

urlpatterns = [
    path("hello/", hello),
    path("board/", board_list),
    path("board/<int:board_no>", board),
    path("board/create/", board_create),
]

POSTMAN에서 GET으로 http://127.0.0.1:8000/api/board/<board_no> 을 실행 합니다.

django restapi pg 15

수정 API

“restapi/views.py” 파일에 “board_update” 함수를 추가 합니다.

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .models import Board
from .serializers import BoardSerializer

# Create your views here.
@api_view(['GET'])
def hello(request):
    return Response("Hello World!")


@api_view(['GET'])
def board_list(request):
    datas = Board.objects.all()
    serializer = BoardSerializer(datas, many=True)

    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['GET'])
def board(request, board_no):
    datas = Board.objects.filter(board_no=board_no)
    serializer = BoardSerializer(datas, many=True)

    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['POST'])
def board_create(request):
    serializer = BoardSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['PUT'])
def board_update(request):
    params = request.data
    data = Board.objects.filter(board_no=params['board_no']).first()
    serializer = BoardSerializer(instance=data, data=params)

    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)

“restapi/urls.py” 파일의 “urlpatterns” 에 “board/update/” 경로를 추가 합니다.

from django.urls import path
from .views import *

urlpatterns = [
    path("hello/", hello),
    path("board/", board_list),
    path("board/<int:board_no>", board),
    path("board/create/", board_create),
    path("board/update/", board_update),
]

POSTMAN에서 Body 값을 아래와 같이 JSON 형식으로 추가 후 PUT으로 http://127.0.0.1:8000/api/board/update/ 을 실행 합니다.

{
  "board_no": 1,
  "title": "제목 수정",
  "contents": "내용 수정",
  "writer": "작성자 수정",
  "view_count": 2,
  "link_url": "https://"
}

django restapi pg 16

삭제 API

$HOME\restapi\views.py 파일에 “board_delete” 함수를 추가 합니다.

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from .models import Board
from .serializers import BoardSerializer

# Create your views here.
@api_view(['GET'])
def hello(request):
    return Response("Hello World!")


@api_view(['GET'])
def board_list(request):
    datas = Board.objects.all()
    serializer = BoardSerializer(datas, many=True)

    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['GET'])
def board(request, board_no):
    datas = Board.objects.filter(board_no=board_no)
    serializer = BoardSerializer(datas, many=True)

    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['POST'])
def board_create(request):
    serializer = BoardSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['PUT'])
def board_update(request):
    params = request.data
    data = Board.objects.filter(board_no=params['board_no']).first()
    serializer = BoardSerializer(instance=data, data=params)

    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)


@api_view(['DELETE'])
def board_delete(request, board_no):
    data = Board.objects.get(board_no=board_no)
    data.delete()

    return Response(status=status.HTTP_204_NO_CONTENT)

“restapi/urls.py” 파일의 “urlpatterns” 에 “board/delete/<int:board_no>” 경로를 추가 합니다.

from django.urls import path
from .views import *

urlpatterns = [
    path("hello/", hello),
    path("board/", board_list),
    path("board/<int:board_no>", board),
    path("board/create/", board_create),
    path("board/update/", board_update),
    path("board/delete/<int:board_no>", board_delete),
]

POSTMAN에서 GET으로 http://127.0.0.1:8000/api/board/delete/<board_no> 을 실행 합니다.

django restapi pg 17

이상으로 기본 API를 구현 해봤습니다.


Written by@[Mr. groove]
There is a difference between knowing the path and walking the path.

GitHub