오늘의 코드 [2022.10.27]
중요해서 반드시 기억할 필요가 있거나, 주의해야 할 코드를 답안 형식으로 저의 코멘트와 함께 정리해 보았습니다.
Q. Django Rest Framework
<데코레이터 함수>
- 튜터님의 파이썬 데코레이터 function 강의 참조
# 예시
def wrapper_function(func):
def decorated_function():
print("함수 이전에 실행")
func()
print("함수 이후에 실행")
return decorated_function
def basic_function():
print("실행하고자 하는 함수")
new_function = wrapper_function(basic_function)
new_function()
# 출력 결과
함수 이전에 실행
실행하고자 하는 함수
함수 이후에 실행
기존에 함수 안에 함수를 집어넣은 결과를 출력하고자 할 때 다음과 같이 작성하였다면
# 예시
def wrapper_function(func):
def decorated_function():
print("함수 이전에 실행")
func()
print("함수 이후에 실행")
return decorated_function
@wrapper_function
def basic_function():
print("실행하고자 하는 함수")
# 출력 결과
함수 이전에 실행
실행하고자 하는 함수
함수 이후에 실행
위와 같이 ‘@’를 추가하여 상위 결과에 해당하는 함수를 입력하면, wrapper_function 함수 내에 basic_function 함수가 입력된다.
<Serializer를 이용한 데이터 조회>
Articles/views.py에서
from rest_framework.response import Response
from rest_framework.decorators import api_view
from articles.models import Article
from articles.serilaizers import ArticleSerializer
@api_view(['GET'])
def index(request):
articles = Article.objects.all()
article = articles[0]
serializer = ArticleSerializer(article)
return Response(serializer)
이렇게 작성하면 다음과 같은 assertion error가 발생하므로

데이터를 올바르게 가져오기 위해서는 아래와 같이 serializer에 .data를 붙여주어야 한다.
@api_view(['GET'])
def index(request):
articles = Article.objects.all()
article = articles[0]
serializer = ArticleSerializer(article)
return Response(serializer.data)
실제로 data를 클릭하면 rest_framework/serializers.py에 다음과 data 함수로 이동하는 것을 알 수 있음
@property
def data(self):
ret = super().data
return ReturnDict(ret, serializer=self)
(Articles/views.py에서)
여러 개의 데이터 셋을 나타나게 하기 위해서는 변수(articles) 뒤에 ‘many=True’를 붙여주는 것을 잊지 말자 (그렇지 않으면 오류 발생)
@api_view(['GET'])
def index(request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
articles/models.py에서
content = models.TextField(null=True, blank=True)
null과 blank에 True를 지정해 주어야 훗날 content 작성 시 오류가 발생하지 않음
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from articles.models import Article
from articles.serilaizers import ArticleSerializer
@api_view(['GET', 'POST'])
def index(request):
if request.method == 'GET':
articles = Article.objects.all()
serializer = ArticleSerializer(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)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- 이전에 로그인 화면 작성했을 때처럼 GET, POST 방식에 맞춰 작성
- GET 방식은 serializer를 통해 articles를 불러오도록(Response) 구성
- POST 방식에서 serializer에서 ArticleSerializer(request.data)라고 착각하기 쉬운데 반드시 data = request.data 형태로 입력해야 한다. 또한, .save()로 저장하기 전에 반드시 유효성 검사 .is_valid()를 해주어야 한다. Response 뒤에 status = status. 하여 호출하고자 하는 HTTP 응답을 지정할 수도 있다.
@api_view(['GET','PUT','DELETE'])
def article_view(request, article_id):
if request.method =='GET':
article = get_object_or_404(Article, id=article_id)
serilaizers = ArticleSerializer(article)
return Response(serilaizers.data)
get_object_or_404 를 통해 url에서 articles/(임의의 숫자)를 입력해도 바로 오류 창이 뜨는 것이 아닌, 아래와 같이 나타남을 알 수 있다.

게시물 수정에 해당하는 PUT 방식의 경우, serializers는 GET과 POST 방식을 혼용한 듯한 구조를 보이는데 ArticleSerializer(article, data=request.data) 는 기존 데이터(article)에서 클라이언트에서 수정된 데이터(data=request.data)로 바꿈을 의미하며 이를 serializer가 인식한다.
@api_view(['GET','PUT','DELETE'])
def article_view(request, article_id):
if request.method =='GET':
article = get_object_or_404(Article, id=article_id)
serilaizer = ArticleSerializer(article)
return Response(serilaizer.data)
elif request.method == 'PUT':
article = get_object_or_404(Article, id=article_id)
serilaizer = ArticleSerializer(article, data = request.data)
if serilaizer.is_valid():
serilaizer.save()
return Response(serilaizer.data)
DELETE 방식을 추가할 때는 데이터를 불러오지 않으므로 serializer가 필요하지 않다.
elif request.method == 'DELETE':
article = get_object_or_404(Article, id=article_id)
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
url에서 기존에 127.0.0.1:8000/articles/index에서 index를 경로에서 제외하고 싶을 때, 아래와 같이 path에서 “” 빈칸으로 두면 된다. (“/” 으로 헷갈리지 않도록 주의)
urlpatterns = [
path("",views.articleAPI, name="index"),
path("<int:article_id>/",views.articleDetailAPI, name="article_view"),
]
(번외편) 포스트맨 사용 시, 훗날 Environments에서 local:host 지정 시 ‘INITIAL VALUE’에 URL 입력할 땐, 가령 http://127.0.0.1:8000 처럼 뒤에 슬래시 없이 입력하는 것을 권장한다. Collections의 request에서 Enter request URL 작성 시, {{host}}/…/ 슬래시 때문에 오류날수 있음(본인도 그것 땜에 시간 많이 소비함..)
'스파르타코딩 AI웹개발 3기' 카테고리의 다른 글
| 내일배움캠프_WIL_2022.10.30 (0) | 2022.10.31 |
|---|---|
| 내일배움캠프_TIL_2022.10.28 (0) | 2022.10.29 |
| 내일배움캠프_TIL_2022.10.26 (0) | 2022.10.26 |
| 내일배움캠프_TIL_2022.10.24 (0) | 2022.10.24 |
| 내일배움캠프_WIL_2022.10.23 (0) | 2022.10.23 |