#10.0 Introduction
- django REST 프레임워크 이용할 것임
- poetry shell해서 가상환경 진입하고, poetry add djangorestframework로 설치
- settings에서 System_apps은 장고가 설치되면서 같이 있는 앱이고, custom_apps은 우리가 만든 우리의 어플리케이션임
THIRD_PARTY_APPS = [
"rest_framework",
]
CUSTOM_APPS = [
"common.apps.CommonConfig",
"users.apps.UsersConfig",
"rooms.apps.RoomsConfig",
"experiences.apps.ExperiencesConfig",
"categories.apps.CategoriesConfig",
"reviews.apps.ReviewsConfig",
"wishlists.apps.WishlistsConfig",
"bookings.apps.BookingsConfig",
"medias.apps.MediasConfig",
"direct_messages.apps.DirectMessagesConfig"
]
SYSTEM_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles'
]
INSTALLED_APPS = SYSTEM_APPS + THIRD_PARTY_APPS + CUSTOM_APPS
- 이렇게하면 REST 프레임워크 설치 끝
- JSON: 하나의 데이터 형식, 코드임
#10.1 JsonResponse
- categories에 대한 API를 만들어볼 것임
- categories안에 urls.py 생성
- config urls로 가서 경로 추가
path("categories/", include("categories.urls"))
- categories의 urls.py에
from django.urls import path
urlpatterns = [
path("",)
]
이렇게 해놓고
- categories의 view로 가서
from django.shortcuts import render
def categories(request):
pass
- 함수에 대한 기능은 차차 작성할 것임
- urls.py이렇게 수정
from django.urls import path
from . import views
urlpatterns = [
path("",views.categories)
]
- 먼저 모든 카테고리를 가져올 것임
- views.py
from .models import Category
from django.http import JsonResponse
def categories(request):
all_categories = Category.objects.all()
return JsonResponse({'ok':True})
- 서버를 열고 categories/로 가면.. 오류가 발생하네?
from django.http import JsonResponse
from .models import Category
def categories(request):
all_categories = Category.objects.all()
return JsonResponse({'ok':True,
'categories':all_categories,
}
)
#10.2 api_view
- django serialization 프레임워크는 장고 모델을 다른 포맷을 변환해주는 방법을 제공함
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
@api_view()
def categories(request):
return Response(
{
"ok": True,
"categories": Category.objects.all(),
}
)
- 다음 시간에 이런 에러를 해결해볼 것임~
#10.3 Serializer
- categories에 serializers.py 생성
- category에 대한 serializer를 만들 것임
from rest_framework import serializers
class CategorySerializer(serializers.Serializer):
pk = serializers.IntegerField()
name = serializers.CharField(required=True)
kind = serializers.CharField()
created_at = serializers.DateTimeField()
- views도 수정
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
from .serializers import CategorySerializer
@api_view()
def categories(request):
all_categories = Category.objects.all()
serializer = CategorySerializer(all_categories, many=True)
return Response(
{
"ok": True,
"categories": serializer.data,
}
)
#10.4 POST Requests
- serializer는 user에게서 온 data를 받아서 우리의 데이터베이스에 넣을 수 있는 django 객체로 바꿔줌
- urls.py
from django.urls import path
from . import views
urlpatterns = [
path("",views.categories),
path("<int:pk>", views.category),
]
- views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
from .serializers import CategorySerializer
@api_view(["GET", "POST"])
def categories(request):
if request.method == "GET":
all_categories = Category.objects.all()
serializer = CategorySerializer(all_categories, many=True)
return Response(serializer.data)
elif request.method == "POST":
Category.objects.create(
name=request.data["name"],
kind=request.data["kind"],
)
return Response({"created": True})
@api_view()
def category(request, pk):
category = Category.objects.get(pk=pk)
serializer = CategorySerializer(category)
return Response(serializer.data)
#10.5 is_valid()
- serializer에게 데이터의 형태를 좀 더 자세히 설명해줌으로써 serializer가 장고 모델에서 JSON으로 번역할 수 있게 함
- serializer가 검증도 해줌
- serializer.py
from rest_framework import serializers
class CategorySerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(required=True,
max_length=50,
)
kind = serializers.CharField(max_length=15,
)
created_at = serializers.DateTimeField(read_only=True)
- views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
from .serializers import CategorySerializer
@api_view(["GET", "POST"])
def categories(request):
if request.method == "GET":
all_categories = Category.objects.all()
serializer = CategorySerializer(all_categories, many=True)
return Response(serializer.data)
elif request.method == "POST":
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
return Response({"created": True})
else:
return Response(serializer.errors)
@api_view()
def category(request, pk):
category = Category.objects.get(pk=pk)
serializer = CategorySerializer(category)
return Response(serializer.data)
#10.6 save()
- 우리는 serializer를 이용해 django 세계의 데이터를 가져와서 JSON으로 번역하는 방법을 배웠고,
- user의 데이터를 받아서 데이터베이스에 저장할 수 있는 category로 번역하는 방법도 배움
- serializer는 save 메소드를 가지고 있음
- **는 딕셔너리를 가져옴
- 이런 느낌
- serializer.py
from rest_framework import serializers
from .models import Category
class CategorySerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(required=True,
max_length=50,
)
kind = serializers.ChoiceField(choices=Category.CategoryKindChoices.choices)
created_at = serializers.DateTimeField(read_only=True)
def create(self, validated_data):
return Category.objects.create(**validated_data)
- views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
from .serializers import CategorySerializer
@api_view(["GET", "POST"])
def categories(request):
if request.method == "GET":
all_categories = Category.objects.all()
serializer = CategorySerializer(all_categories, many=True)
return Response(serializer.data)
elif request.method == "POST":
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
new_category = serializer.save()
return Response(
CategorySerializer(new_category).data,
)
else:
return Response(serializer.errors)
@api_view()
def category(request, pk):
category = Category.objects.get(pk=pk)
serializer = CategorySerializer(category)
return Response(serializer.data)
#10.7 update()
- 장고 REST 프레임워크에 GET와 PUT 요청을 허용
- PUT 요청은 POST요청이랑 비슷함
- partial=True : serializer는 여기로 들어오는 데이터가 완벽한 형태가 아닐 수도 있다는 것을 알게 됨
- serializer.py
from rest_framework import serializers
from .models import Category
class CategorySerializer(serializers.Serializer):
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(required=True,
max_length=50,
)
kind = serializers.ChoiceField(choices=Category.CategoryKindChoices.choices)
created_at = serializers.DateTimeField(read_only=True)
def create(self, validated_data):
return Category.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.name = validated_data.get("name", instance.name)
instance.kind = validated_data.get("kind", instance.kind)
instance.save()
return instance
- views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
from .serializers import CategorySerializer
from rest_framework.exceptions import NotFound
@api_view(["GET", "POST"])
def categories(request):
if request.method == "GET":
all_categories = Category.objects.all()
serializer = CategorySerializer(all_categories, many=True)
return Response(serializer.data)
elif request.method == "POST":
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
new_category = serializer.save()
return Response(
CategorySerializer(new_category).data,
)
else:
return Response(serializer.errors)
@api_view(["GET", "PUT"])
def category(request, pk):
try:
category = Category.objects.get(pk=pk)
except Category.DoesNotExist:
raise NotFound
if request.method == "GET":
serializer = CategorySerializer(category)
return Response(serializer.data)
elif request.method == "PUT":
serializer = CategorySerializer(
category,
data=request.data,
partial=True,
)
if serializer.is_valid():
updated_category = serializer.save()
return Response(CategorySerializer(updated_category).data)
else:
return Response(serializer.errors)
#10.8 DELETE
- views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
from .serializers import CategorySerializer
from rest_framework.exceptions import NotFound
from rest_framework.status import HTTP_204_NO_CONTENT
@api_view(["GET", "POST"])
def categories(request):
if request.method == "GET":
all_categories = Category.objects.all()
serializer = CategorySerializer(all_categories, many=True)
return Response(serializer.data)
elif request.method == "POST":
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
new_category = serializer.save()
return Response(
CategorySerializer(new_category).data,
)
else:
return Response(serializer.errors)
@api_view(["GET", "PUT", "DELETE"])
def category(request, pk):
try:
category = Category.objects.get(pk=pk)
except Category.DoesNotExist:
raise NotFound
if request.method == "GET":
serializer = CategorySerializer(category)
return Response(serializer.data)
elif request.method == "PUT":
serializer = CategorySerializer(
category,
data=request.data,
partial=True,
)
if serializer.is_valid():
updated_category = serializer.save()
return Response(CategorySerializer(updated_category).data)
else:
return Response(serializer.errors)
elif request.method == "DELETE":
category.delete()
return Response(status=HTTP_204_NO_CONTENT)
- config-urls.py
"""
URL configuration for config project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path("api/v1/rooms/", include("rooms.urls")),
path("api/v1/categories/", include("categories.urls"))
]
#10.9 Recap
- serializer.save는 create메소드를 실행시킴
- 사용자가 준 검증된 데이터와 함꼐 create 호출 된다.
#10.10 APIView
- views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Category
from .serializers import CategorySerializer
from rest_framework.exceptions import NotFound
from rest_framework.status import HTTP_204_NO_CONTENT
from rest_framework.views import APIView
class Categories(APIView):
def get(self, request):
all_categories = Category.objects.all()
serializer = CategorySerializer(all_categories, many=True)
return Response(serializer.data)
def post(self, request):
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
new_category = serializer.save()
return Response(
CategorySerializer(new_category).data,
)
else:
return Response(serializer.errors)
class CategoryDetail(APIView):
def get_object(self, pk):
try:
return Category.objects.get(pk=pk)
except Category.DoesNotExist:
raise NotFound
def get(self, request, pk):
serializer = CategorySerializer(self.get_object(pk))
return Response(serializer.data)
def put(self, request, pk):
serializer = CategorySerializer(
self.get_object(pk),
data=request.data,
partial=True,
)
if serializer.is_valid():
updated_category = serializer.save()
return Response(CategorySerializer(updated_category).data)
else:
return Response(serializer.errors)
def delete(self, request, pk):
self.get_object(pk).delete()
return Response(status=HTTP_204_NO_CONTENT)
- categories-urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.Categories.as_view()),
path("<int:pk>", views.CategoryDetail.as_view()),
]
#10.11 ModelSerializer
- 이렇게나 간단해질 수 있는 거구나…
- serializer.py
from rest_framework import serializers
from .models import Category
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = "__all__"
- views.py
from rest_framework.decorators import api_view
from rest_framework.exceptions import NotFound
from rest_framework.response import Response
from rest_framework.status import HTTP_204_NO_CONTENT
from rest_framework.views import APIView
from .models import Category
from .serializers import CategorySerializer
class Categories(APIView):
def get(self, request):
all_categories = Category.objects.all()
serializer = CategorySerializer(
all_categories,
many=True,
)
return Response(serializer.data)
def post(self, request):
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
new_category = serializer.save()
return Response(
CategorySerializer(new_category).data,
)
else:
return Response(serializer.errors)
class CategoryDetail(APIView):
def get_object(self, pk):
try:
return Category.objects.get(pk=pk)
except Category.DoesNotExist:
raise NotFound
def get(self, request, pk):
serializer = CategorySerializer(self.get_object(pk))
return Response(serializer.data)
def put(self, request, pk):
serializer = CategorySerializer(
self.get_object(pk),
data=request.data,
partial=True,
)
if serializer.is_valid():
updated_category = serializer.save()
return Response(
CategorySerializer(updated_category).data,
)
else:
return Response(serializer.errors)
def delete(self, request, pk):
self.get_object(pk).delete()
return Response(status=HTTP_204_NO_CONTENT)
#10.12 ModelViewSet
- viewset? 말도 안 되게 좋은 기능
- views에 작성한 거 다 지워
- modelviewset을 import해
- 코드는 더 간단하지만 우리가 서버에서 직접 html코드로 안 써도 되게 html 폼까지 만들어줌
- urls.py
from django.urls import path
from . import views
urlpatterns = [
path(
"",
views.CategoryViewSet.as_view(
{
"get": "list",
"post": "create",
}
),
),
path(
"<int:pk>",
views.CategoryViewSet.as_view(
{
"get": "retrieve",
"put": "partial_update",
"delete": "destroy",
}
),
),
]
- views.py
from rest_framework.decorators import api_view
from rest_framework.exceptions import NotFound
from rest_framework.response import Response
from rest_framework.status import HTTP_204_NO_CONTENT
from rest_framework.views import APIView
from .models import Category
from .serializers import CategorySerializer
from rest_framework.viewsets import ModelViewSet
class CategoryViewSet(ModelViewSet):
serializer_class = CategorySerializer
queryset = Category.objects.all()
#10.13 Conclusions
- 우리는 urls.py를 통해 viewset으로 http 메소드랑 viewset메소드랑 연결해야 했음
- 근데 라우터를 이용해서 한 번에 처리할 수 있음
- 근데 너무 다 해줘서 개발자가 원하는 기능을 세세하게 구현하려면 직접하는게 나을거다.
'Backend > Django' 카테고리의 다른 글
[백엔드][Django][장고 채널스] Section1. openAI API 살펴보기 (0) | 2023.07.23 |
---|---|
[백엔드][Django][장고 채널스] Section0. Overview (0) | 2023.07.23 |
[백엔드][장고][Django] Chapter #9 (0) | 2023.07.17 |
[백엔드][장고][Django] Chapter #8 (0) | 2023.07.17 |
[백엔드][장고][Django] Chapter #7 (0) | 2023.07.17 |
Uploaded by Notion2Tistory v1.1.0