web/django

Django View 설계하기

민사민서 2024. 5. 7. 02:28

HTTP Request Method

  • GET : 데이터 조회
  • POST:  요청 데이터 처리, 주로 등록에 사용
  • PUT : 데이터를 대체(덮어쓰기), 해당 데이터가 없으면 생성
  • PATCH : 데이터 부분 변경 (PUT이 전체 변경, PATCH는 일부 변경)
  • DELETE : 데이터 삭제
  • HEAD : GET과 동일하지만 메시지 부분(body 부분)을 제외하고, 상태 줄과 헤더만 반환
  • OPTIONS : 대상 리소스에 대한 통신 가능 옵션(메서드)을 설명(주로 CORS에서 사용)
  • CONNECT : 대상 자원으로 식별되는 서버에 대한 터널을 설정
  • TRACE : 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행

C, U의 경우 data를 request Body에 넣어서 JSON 형태로 보내준다

 

cf) why JSON?

  • 가볍고 (lightweight)
  • 가독성이 좋으며 (human-readable)
  • 범용적으로 사용된다 (widely supported)

 

View를 만드는 방법

1. Function Based View (FBV)

장점: 함수를 직접 만들어 원하는 기능을 직접 구현할 수 있으며 심플하고 가속성이 좋다.

단점: 확장, 재사용이 어렵다. 또한 조건문으로 HTTP 메소드를 구분해야하는 단점이 있다.

 

2. Class Based View (CBV)

장점: 확장, 재사용이 용이하며, 다중상속이 가능하고, HTTP 메소드가 클래스 안에서 나누어 처리가 가능하다.

단점: 코드 흐름이 암시적이어서 읽기 어려우며, 상속되고 믹스되면서 코드 이해를 위해 찾아다녀야 한다.

 

Django에서는 CBV를 대비해 많은 Tools(클래스)들을 제공해주고 있음

 

프로젝트의 url mapping 세팅

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

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

// seminar/urls.py 에다가 urlpatterns 를 추가해준다

 

FBV 방식으로 View 만들기

from rest_framework.response import Response
from rest_framework.decorators import api_view
from .models import Post

# Create your views here.

@api_view(['POST'])
def CreatePostView(request):
  title = request.data.get('title')
  content = request.data.get('content')
  post = Post.objects.create(title=title, content=content)
  return Response({"msg": f"Post {post.title} created successfully!"})

@api_view(['GET'])
def ReadAllPostView(request):
  posts = Post.objects.all()
  content = [{post.title: post.content} for post in posts]
  return Response({"posts": content})

// post/views.py 를 이런 식으로 만들 수 있음

 

- decorator를 통해 뷰의 해당 함수가 처리할 request의 method 종류를 미리 정해둠 (https://www.django-rest-framework.org/api-guide/responses/#:~:text=Creating%20responses-,Response(),-Signature%3A%20Response )

ex) @api_view(['GET', 'PUT']) 이렇게 쓰면 GET, PUT 메서드를 수행, 내부에서 request.method == 'GET' 이런 식으로 분기 필요

// decorator로 지정 안 한 메서드는 이렇게 뜨네

 

from django.urls import path
from .views import CreatePostView, ReadAllPostView

app_name = 'post'
urlpatterns = [
  path('register_post/', CreatePostView, name='post'),
  path('all_posts/', ReadAllPostView, name='get'),
]

// post/urls.py 를 요런 식으로 만들 수 있음

 

 

View 만들기 using CBV

장고 CBV 종류

추상화 정도

APIView < mixins < generics APIView < ViewSet

 

특징

  • APIView : 자주 쓰이는 view 들의 패턴을 패턴화 시켜 최소한의 코드로 Model 에 대한 view 를 구현하는 방법.
  • mixins : APIView 의 일반적인 로직들을 섞어 재사용성을 높임.
  • generics APIView : mixins 사용을 패턴화하여 정리.
  • ViewSet : generics APIViews 를 한번 더 합쳐서 정리.

post/veiws.py

from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from .models import Post

class PostListView(APIView):
  def get(self, request):
    posts = Post.objects.all()
    contents = [{"id": post.id,
                 "title": post.title,
                 "content": post.content,
                 "created_at": post.created_at} for post in posts]
    return Response(contents, status=status.HTTP_200_OK)
  
  def post(self, request):
    title = request.data.get('title')
    content = request.data.get('content')
    if not title or not content:
      return Response({"msg": "title and content are required"}, status=status.HTTP_400_BAD_REQUEST)
    post = Post.objects.create(title=title, content=content)
    return Response({
      "id": post.id,
      "tiotle": post.title,
      "content": post.content,
      "created_at": post.created_at
    }, status=status.HTTP_201_CREATED)

 

- request body의 data는 request.data.get() 으로 가져온다

- Post.objects.create() => DB에 데이터 추가 // django queryset 문법

https://docs.djangoproject.com/en/4.1/ref/models/querysets/#create:~:text=method%20was%20added.-,create()%C2%B6,-create(**

- Response 클래스를 이용해 JSON 형태로 응답을 되돌려보냄, status 값과 함께

 

class PostDetailView(APIView):
  def get(self, request, post_id):
    try:
      post = Post.objects.get(id=post_id)
    except:
      return Response({"msg": "Post not found"}, status=status.HTTP_404_NOT_FOUND)
    return Response({
      'id': post.id,
      'title': post.title,
      'content': post.content,
      'created_at': post.created_at
    }, status=status.HTTP_200_OK)
  
  def delete(self, request, post_id):
    try:
      post = Post.objects.get(id=post_id)
    except:
      return Response({"msg": "Post not found"}, status=status.HTTP_404_NOT_FOUND)
    post.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

 

- 특정한 게시글에 접근하는 뷰, url에 post_id 값이 담겨온다

- post.delete() 통해 DB에 저장된 데이터 삭제

https://docs.djangoproject.com/en/4.1/topics/db/queries/#deleting-objects:~:text=other_obj.name-,Deleting%20objects%C2%B6,-The%20delete%20method

 

post/urls.py

from django.urls import path
from .views import PostListView, PostDetailView

app_name = 'post'
urlpatterns = [
    path('', PostListView.as_view()),
    path('<int:post_id>/', PostDetailView.as_view())
]

 

앱의 urls.py 에서는 app_name을 명시해주어야 한다

/api/post/ 는 PostListView라는 뷰에 의해 처리되고 /api/post/xxx/ 는 PostDetailView라는 뷰에 의해 처리될 것