GitHub

https://github.com/Choidongjun0830

노마드 코더 Airbnb 클론 코딩

노마드 코더 에어비앤비 클론 코딩 #10 Django Rest Framework

gogi masidda 2022. 11. 5. 11:54

@api_view()

유저에게 HttpResponse를 전달하면 안되고, JSON을 전달해야한다.

Json에서는 'return JSONResponse({"categories":all_categories})'처럼 변수를 보내면 오류가 난다.

그래서 QuerySet을 JSON포맷으로 변환해야한다.

Django Rest Framework를 사용하여 변환할 수 있다.

#예
from rest_framework.response import Response
from .models import Category

@api_view()
def categories(request):
	return Response(...)

apiview를 이용한 어드민 패널

 

Serializer: python말로 Django말을 JSON으로 바꿔주고, 반대로 JSON을 Django말로 바꾸주는 역할을 함. user 데이터를 받아 Django 객체로 바꿔준다.

App 폴더 안에 'serializers.py'를 만들어야한다. 이 파일로 모델이 API 바깥 세상으로 갈 때, 어떻게 표시될지 정할 수 있다.

class AppSerializer(serializers.Serializer):
	#카테고리 필드 중 어떤 부분을 보여줄지.
    #필드 = serializers.필드 타입
    
#models.py에서 한 것과 비슷함
#views.py에 작성해야하는 Django Rest Framework를 위한 함수
def 함수명 (request):
	데이터명 = 데이터 받기 #all_categories = Category.objects.all()
    serialzer = serializer.py에서 만든 클래스명(데이터명, many=True) #받은 데이터가 여러개일 경우 many=True를 써줘야함
    return Response(serializers.data)

 

POST Requests: 어드민 패널에서 새로운 데이터를 추가하는 기능이다.

'@api_view(["GET","POST"])

POST 기능이 추가된 모습

 

is_valid

user로 부터 데이터를 받아 django모델을 만드는 데에는 serializer가 필요하다.

serializer = serializer명(data=...)
#예
serializer = CategorySerializer(data=request.data)

serializer에게 user가 보낸 데이터의 유효성 검사를 맡길 수 있다.

serializer.is_valid() #유효한지
serializer.errors #에러가 어디서 났는지

 

save()

request.data(유저가 만든 데이터, post로 객체를 만들 때.)로만 생성한 serializer에서 save()를 호출하면(serializer=serializer명(data=request.data)로 save()를 실행하면), Django는 자동으로 serializers.py에서 create() 메소드를 찾는다.

여기서 create() 메소드는 새로운 객체를 넘겨주던가, 에러를 넘겨주던가 해야함.

 

위 사진에서,  'serializer = CategorySerializer(data=request.data)'를 실행하면 serializers.py에 있는 create()를 호출함.

serializers.py에 작성한 create() 메소드

pk와 created_at에 있는 'read_only=True'는 유저가 보내는 데이터가 아니기 때문에 읽기전용으로 만드는 것이다.

create() 메소드의 vaildated_data는 views.py로 부터 오는 유효한 데이터이다.

'**vaildated_data'에서 **은 딕셔너리를 가져온다는 뜻이다.

그런데 {'name':'Category', 'kind':'rooms'}를 name = 'Category', kind = 'rooms'의 형태로 바꿔서 가져온다. 그리고 이것을 create() 메소드가 필요로 한다.

create()가 잘 실행된 모습

 

update()

PUT 요청은 POST와 비슷하다.

update()는 원래의 데이터에 유저 데이터를 추가해야하고, 또 그 데이터의 유효성을 검사해야하기 때문에 serializer를 한 번 더 선언해야한다.

views.py

serializer = CategorySerializer(category,data=request.data, partial=True)
#category는 원래의 데이터, data=request.data는 추가될 유저 데이터
#partial=True는 데이터를 갱신할 때, 필수인 데이터를 완벽한 형태로 입력하지 않아도 된다. name이 필수 항목이지만 갱신 시에는 kind만 입력해도 된다.

이번에는 save()와 달리, 유저 데이터로만 객체를 생성하는 것이 아니다. 그래서 create() 메소드가 아니라 update() 메소드가 호출된다.

update 메소드

여기서 '.get()'은 딕셔너리 메소드로, if문을 대신해여 사용할 수 있다. 

.get()("찾을 값","못찾을 경우 반환할 값")

그래서 name만 갱신되었을 경우에는 새로운 name을 반환하고 kind는 그대로, kind가 갱신되면 새로운 kind를 반환하고 name은 그대로 반환하게 된다.

 

delete

다른 메소드와 마찬가지로 하면된다.

...
elif request.method = "DELETE":
	category.delete()
    return Response(status=HTTP_204_NO_CONTENT)

어드민 패널에서 delete가 실행되는 모습

 

APIView: 이전에 if request.method = "GET"처럼 작성한 GET과 POST를 대체해준다.

APIVIEW를 이용한 views.py

from rest_framework.views import APIView
...
class 클래스명(APIView):
	def get():
    	...
   	def post():
    	...

이전에 작성했던 코드와 같은 기능이지만, 더 쉽고, 더 짧은 코드를 만들 수 있다. 

 

이전에 pk를 통해 category 하나하나를 들어가는 함수를 바꾼 것이다. 

get_object() 함수로 pk에 맞는 category를 가져온다.

urls.py

이전에 작성했던 코드가 사라지고 새로운 이름의 함수와 클래스가 생겼으므로 urls.py도 바꿔주어야한다.

이번에는 'class Categories(APIView)'를 가져와야한다.

'as_view()'를 이용하여 클래스를 가져올 수 있다. 그리고 as_view가 GET이면 get함수, POST면 post함수를 실행시킨다.

 

ModelSerializer

지금은 Category에 모델이 적어서 괜찮지만, 나중에 모델이 많아지면 하나하나 선언하는 것이 번거로울 수 있다. 그리고 models.py에 작성한 코드와 거의 비슷하다.

serializer.py에 있던 'CategorySerializer(serializers.Serializer):'대신 serializers.ModelSerializer를 사용하여 중복되는 코드를 피할 수 있다.

serializers.ModelSerializer에는 .create()와 .update()가 기본으로 내장되어있고, models.py에 작성한 model의 field를 자동으로 파악한다.

#serializer.py
...

class CategorySerializer(serializers.ModelSerializer):
	class Meta:
    	model = Category. #serializer가 Category 모델을 위한 serializer를 만들어주고 create, update 기능까지 만들어준다.
	fields = ("포함시킬 필드") # field = "__all__" 전부 보여주기
        exclude = ("제외시킬 필드") #field와 exclude 중 하나만 쓰면 된다.

 

ModelViewSet

views.py에 있던 모든 코드를 대체할 수 있다.

ModelViewSet에는 두가지 property가 있어야한다.

1. serializer가 뭔지

2. viewset의 object가 뭔지

from rest_framework.viewsets import ModelViewSet
...

class CategoryViewSet(ModelViewSet):
	serializer_class = CategorySerializer #1
    	queryset = Category.objects.all() #2

그리고, urls.py에 각 페이지에서 사용할 메소드를 설정해야한다.

viewset의 메소드와 사용자가 admin한테 보낼 HTTP 메소드를 연결시킨다.

urls.py

첫번째 urlpatterns는 모든 Category들을 볼 수 있는 페이지고, 두번째는 pk를 이용하여 하나씩 볼 수 있는 페이지다.

api admin패널. POST 기능이 잘 작동하는 모습

 

하지만 ModelViewSet의 기능 안에서만 코드를 작성한다면 유용하겠지만, destroy를 overriding하거나, 더욱 명확한 코드를 위해선 이전처럼 APIView를 이용하여, 하나하나씩 작성하는게 나을 수도 있다.

 

 

728x90