RESTful
- URI (고유한 주소) > URL (like 파일위치) : API에서는 URI라고 하는 것이 더 정확하다.
- URI 설계
- 컬렉션은 복수를 사용한다.
- CRUD는 URI에 사용하면 안된다.
- Create:
POST
- Read:
GET
- Update:
PUT
(통째로 교체) - Destroy:
DELETE
- +)
PATCH
(Update, 일부분만 교체)
- Create:
Class-based views
- 재사용가능한 뷰를 만들기 좋다.
- 모든 뷰는
View
클래스를 상속받아 사용한다.
Introduction to class-based views
- 특정 HTTP 메소드 (GET, POST 등)와 관련된 코드의 구성을 조건문 분기 대신 별도의 메소드로 처리
- 믹스인(다중 상속)과 같은 객체 지향 기술을 사용하여 코드를 재사용 가능
- Mixin : 기본적으로 사용하는 것에 추가하여 사용한다는 의미
- 예:
class TemplateView(TemplateResponseMixin, ContextMixin, View)
- 기본적으로 사용되는
View
에 기능확장을 위해 두 가지mixin
을 추가 - 믹스인을 잘 사용하면 자신에게 필요한
CustomView
를 만들기 유용
The relationship and history of generic views, class-based views, and class-based generic views
Only view function > Function-based Generic View > Class-based Generic View
- Generic View : 자주 쓰이는 뷰들을 추상화된 공통적인 패턴으로 정의 (가장 많이 사용)
Using class-based views
클래스 기반 뷰를 사용하면 조건문 분기 코드가 아닌 다른 클래스 인스턴스 메서드를 사용하여 여러 HTTP 요청 메서드에 응답 할 수 있다.
뷰 함수에서 HTTP GET을 처리 할 코드는 다음과 같다.
# view function
from django.http import HttpResponse
def my_view(request):
if request.method == 'GET':
# <view logic>
return HttpResponse('result')
클래스 기반 뷰에서는 다음과 같다.
# class-based view
from django.http import HttpResponse
from django.views import View
class MyView(View):
# get 요청 처리
def get(self, request):
# <view logic>
return HttpResponse('result')
장고 URL resolver는 request와 (클래스가 아니라) 함수가 올것을 기대한다. 클래스 기반 뷰는 as_view()
메서드를 가지고 있는데, 이 메서드는 URL과 매치되는 패턴이 도착하면 함수를 반환한다. 이 함수는 클래스의 인스턴를 만들고 dispatch()
메서드를 호출한다.
dispatch()
는 요청이 GET, POST 등인지 여부를 확인하고 일치하는 메소드가 정의되어있는 경우 해당 요청을 중계하거나 그렇지 않은 경우 HttpResponseNotAllowed를 발생시킨다.
# urls.py
from django.conf.urls import url
from myapp.views import MyView
urlpatterns = [
url(r'^about/$', MyView.as_view()),
]
Using mixins
믹스인은 여러 상위 클래스의 행위와 속성을 결합 할 수있는 다중 상속의 한 형태이다.
- 여러 클래스에서 코드를 재사용 할 수있는 훌륭한 방법이다.
- 하지만, 많은 코드가있는 클래스를 상속하는 경우 어떤 mixins에서 어떤 메소드를 재정의 할 것인지를 아는 것이 어렵다.
- 주의 : 하나의 generic view에서만 상속 할 수 있다.
- 예를 들어, 하나의 상위 클래스
View
에서 상속 할 수 있으며 - 나머지는 (있는 경우) 믹스인 이어야한다.
- 예를 들어, 하나의 상위 클래스
Django REST Framework
Tutorial 1: Serialization
- Serializers
-
querysets 및 모델 인스턴스와 같은 복잡한 데이터를
JSON
,XML
또는 (기타 컨텐트 유형으로 쉽게 렌더링 할 수있는)native Python
데이터 유형으로 변환한다.
Serializer
snippet
인스턴스를 json
과 같은 표현으로 serializing 및 deserializing해야 한다. serializers
를 사용해 쉽게 구현할 수 있다.
from rest_framework import serializers
from snippets.models import Snippet
# 파이썬 객체로 만들고(create), 업데이트(update)하는 클래스
class SnippetSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
# ...
def create(self, validated_data):
# create(**kwargs) : 딕셔너리 형 데이터의 key-value를 자동으로 넣어 처리
return Snippet.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
# ...
# 객체 인스턴스가 장고 모델과 일치하면 데이터베이스에 저장 가능
instance.save()
return instance
ModelSerializers
# ModelSerializer class
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
# create() 메서드와 update() 메서드가 이미 구현되어 있다.
Postman 테스트
Postman > POST method Body > Raw > Json 으로 요청
{
"title": "Test Snippet",
"code": "class MyUser(AbstractUser):\n\timg_profile = models.ImageField(upload_to='user', blank=True)",
"linenos": true,
"language": "python",
"style": "default"
}
Tutorial 2: Requests and Responses
Adding optional format suffixes to our URLs
Response
객체는 클라이언트가 요청한 형태로 콘텐츠를 렌더링한다. 이 장점을 활용하기 위해, API를 개선한다. 다음과 같은 URI를 사용할 수 있게 된다.
- http://example.com/api/items/4
- http://example.com/api/items/4.json
- http://example.com/api/items/4.xml (XML 제공)
Browsability
web-browsable API를 지원하지만, 실제 production에 사용하면 안된다.
Tutorial 3: Class-based Views
Using mixins
# GenericAPIView 제너릭뷰로 받고,
# GET 요청이면 ListModelMixin으로 실행
# POST 요청이면 CreateModelMixin으로 실행
class SnippetList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
# 직렬화 함수는 1개만 사용 가능
serializer_class = SnippetSerializer
# GET 요청
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
# POST 요청
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
Using generic class-based views
생성/조회/업데이트/삭제는 굉장히 일반적인 일이다. 그래서 REST framework는 mixed-in generic view로 제공한다.
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
과제
- API 테스트 코드 작성 (참고)