Meme's IT

[Django] DRF(1) single model 본문

BackEnd/Django

[Django] DRF(1) single model

Memez 2023. 10. 18. 12:56

DRF를 우선 하나의 모델에서 해보자

이때, html파일은 작성하지 않음 → 결과를 확인하기 위해 POSTMAN이라는 프로그램을 이용

 

 

앞에서 했던 게시판 CRUD를 DRF로 해보자

앞선 방법과 달리, 함수 & URL은 두개만 있어도 충분함

왜냐하면 HTTP method를 바꿔가며 각각 필요에 따라 사용할 것이기 때문!

 


우선 사전준비로

가상 환경, 패키지, migrate, fixture파일 load까지

 

1. GET(데이터 조회하기) - 전체 게시글 조회

(1) serializers.py에 ArticleListSerializer정의해주기

(예전에 ModelForm과 비슷함)

# articles/serializers.py

from rest_framework import serializers
from .models import Article

class ArticlelistSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ('id', 'title', 'content',)

이때, serializers.py의 위치나 파일명은 자유롭게 작성 가능!

 

(2) url 작성

# articles/urls.py

urlpatterns = [
    path('articles/',views.article_list),
]

굳이 name을 정해줄 필요가 없음

 

(3) view 함수 작성

# articles/views.py

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

from .models import Article
from .serializers import ArticlelistSerializer


@api_view(['GET'])
def article_list(request):
    articles = Article.objects.all()
    serializer = ArticlelistSerializer(articles, many=True)
    return Response(serializer.data)

여기서 @api_view란?

더보기

# 'api_view' decorator

- DRF view 함수에서는 필수로 작성, HTTP 메서드를 확인하는 역할

- 기본적으로는 GET만 허용되며 다른 요청에 대해서는 405 Method Not Allowed로 응답됨

- DRF view 함수가 응답해야하는 HTTP 메서드 목록을 작성해준다!

 

 

 

(4) POSTMAN으로 응답확인

http://127.0.0.1:8000/api/v1/articles/ 로 확인가능

 

 

2. GET - Detail, 단일 게시글 조회

(1) 각 게시글의 상세 정보를 제공하는 serializers 새로 정의

# articles/serializers.py

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'	# 모든 항목 조회

(2) url 추가

# articles/urls.py

urlpatterns = [
    path('articles/',views.article_list),
    paht('articles/<int:article_pk>/',views.article_detail),	# 추가
]

(3) view 함수 작성

# articles/views.py

from .serializers import ArticlelistSerializer, ArticleSerializer	# 새로운 serializer 추가

@api_view(['GET'])
def article_detail(request, article_pk):
    article = Article.objects.get(pk=article_pk)
    serializer = ArticleSerializer(article)
    return Response(serializer.data)

(4) POSTMAN에서 확인

http://127.0.0.1:8000/api/v1/articles/3/

▶참고: 만약 게시글 조회할 때마다 조회수를 올려주고 싶다면?

더보기

1. models.py에서 조회수를 추가해준다.

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    # 조회수는 상세 페이지에서만 조회 가능하다고 가정
    views = models.IntegerField(default=0)	# 추가

2. views.py함수에서 조회수 추가하는 기능을 추가해준다.

@api_view(['GET'])
def article_detail(request, article_pk):
    article = get_object_or_404(Article, pk=article_pk)
    if request.method == 'GET':
        # 조회수 추가
        article.views += 1
        article.save()
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

 

 

3. POST - 새로운 게시글 작성하기

  • 데이터 생성이 성공하면 201 Created를 응답
  • 데이터 생성이 실패하면 400 Bad request를 응답

(1) article_list view함수 변경

url과 새로운 함수를 안만들어도 된다!

새로운 게시글을 만드는 것이므로 url중 위에 해당하는 함수에 추가해줌

# articles/urls.py
from rest_framework import status	# 추가
	
@api_view(['GET','POST'])
def article_list(request):		# 업데이트
    if request.method == 'GET':
        articles = Article.objects.all()
        serializer = ArticlelistSerializer(articles, many=True)
        return Response(serializer.data)
    
    elif request.method == 'POST':
        serializer = ArticleSerializer(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)

 

(2) POSTMAN으로 확인 

  • http://127.0.0.1:8000/api/v1/articles/의 URL사용
  • 꼭! POST형식으로 Send하기
  • Body부분에 새로 만들고자하는 데이터 입력

각각 입력후 send

새로운 글 확인 가능

 


4. DELETE - 글 지우기

글 지우는 거는 하나의 글을 지우는 것이므로 두번째 함수 사용

(1) view 함수 수정

# articles/views.py

@api_view(['GET', 'DELETE'])
def article_detail(request, article_pk):
    article = Article.objects.get(pk=article_pk)

    if request.method == 'GET':
        serializer = ArticleSerializer(article)
        return Response(serializer.data)
    
    elif request.method == 'DELETE':
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

(2) POSTMAN으로 확인

  • http://127.0.0.1:8000/api/v1/articles/18/ 으로 확인(18은 지우려는 글의 pk)
  • DELETE로 바꿔주기
  • 204 No Content 확인

참고: 만약 삭제되었다는 메세지를 출력하고 싶다면

더보기
elif request.method == 'DELETE':
        article.delete()
        # 삭제 메세지를 주고싶다면
        return Response({'message':'삭제완료'}, status=status.HTTP_200_OK)

딕셔너리 형태로 추가해 준다

 

 

5. PUT - 게시글 수정하기

(1) view 함수 수정하기

얘도 각각의 글을 수정하는 것이므로 두번째 함수 사용

# articles/views.py

@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
    article = Article.objects.get(pk=article_pk)

    if request.method == 'GET':
        serializer = ArticleSerializer(article)
        return Response(serializer.data)
    
    elif request.method == 'DELETE':
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
    
    elif request.method == 'PUT':
        serializer = ArticleSerializer(article, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

(2) POSTMAN으로 확인

  • PUT으로 
  • Body에 수정할 내용 입력

 

.

.

.

 

근데, 제목 / 내용만 수정하고 싶을때는..?

 

# articles/serializers.py

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'	# 여기가 all로 되어있어서 모든 데이터를 입력해줘야함

all로 되어있어서 모든 데이터에 대해서 유효성 검사를 진행함,

그래서 view함수를 수정해줌

# articles/views.py

@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
    article = Article.objects.get(pk=article_pk)

   	...
    
    elif request.method == 'PUT':
        serializer = ArticleSerializer(article, data=request.data, partial=True) # partial옵션추가
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

partial = True라는 옵션을 추가해주면 된다

'BackEnd > Django' 카테고리의 다른 글

[Django] API 문서화  (0) 2023.10.19
[Django] DRF(2) N:1 Relation  (0) 2023.10.19
[Django] DRF란?  (0) 2023.10.18
[Django] RESTful API (2) 자원의 행위 / 표현  (0) 2023.10.18
[Django] RESTful API (1) URI과 URL  (0) 2023.10.18