Generic views - Methods
Base methods:
get_queryset(self)
이 메서드는 리스트 뷰, 디테일 뷰의 조회를 위해 사용되는 쿼리셋을 반환한다.
queryset
의 지정된 속성에 따라 반환되는 것이 기본값이다.
self.queryset
보다 이 매서드를 사용해야한다. self.queryset
은 결과를 이후 모든 리퀘스트에 캐시되기 때문이다.
유저의 리퀘스트에 따른 쿼리셋 반환처럼 다양한 요청에 응답하기 위해 오버라이드할 수도 있다.
For example:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
만약 generic view에서 serializer_class를 사용한다면 n+1과 같은 문제를 해결하기 위해 이 메서드에서select_related
와 prefetch_related
를 이용해 퀴리셋을 최적화 할 수 있다.
n+1 문제와 언급된 방법의 사례는 django documentation의 관련 섹션을 참조하라.
get_object(self)
이 메서드는 디테일 뷰에서 사용하기 위해 객체 인스턴스를 반환한다.
기본 쿼리셋을 필터링하기 위해 lookup_field
파라미터를 사용하는 것이 기본값이다.
둘 이상의 URL kwarg를 조회하는 것과 같이 복잡한 작업을 수행하기 위해 오버라이드 할 수 있다.
For example:
def get_object(self):
queryset = self.get_queryset()
filter = {}
for field in self.multiple_lookup_fields:
filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter)
self.check_object_permissions(self.request, obj)
return obj
만약 API에 객체 레벨(수준)의 권한을 포함하지 않는다면, 예제의 self.check_object_permissions
을 제외하고get_object_or_404
을 통해 객체를 간단히 반환할 수 있다.
filter_queryset(self, queryset)
쿼리셋을 넣으면 사용 중인 어느 백엔드 필터든 그것을 필터링하여 새 쿼리셋을 반환한다.
For example:
def filter_queryset(self, queryset):
filter_backends = [CategoryFilter]
if 'geo_route' in self.request.query_params:
filter_backends = [GeoRouteFilter, CategoryFilter]
elif 'geo_point' in self.request.query_params:
filter_backends = [GeoPointFilter, CategoryFilter]
for backend in list(filter_backends):
queryset = backend().filter_queryset(self.request, queryset, view=self)
return queryset
get_serializer_class(self)
serializer에 사용하는 클래스를 반환한다.
기본값은 serializer_class
속성을 반환한다.
다른 serializers를 사용하거나 다른 사용자에게 serializers를 제공하는 것과 같이 다양한 작업을 수행하기 위해 오버라이드 할 수 있다.
For example:
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
Save and deletion hooks:
다음 메서드는 mixin 클래스에서 제공하며, 객체 저장 또는 삭제 동작을 쉽게 오버라이드할 수 있도록 한다.
perform_create(self, serializer)
- 새로운 인스턴스를 저장할 때,CreateModelMixin
에 의해 호출된다.
perform_update(self, serializer)
- 기본 인스턴스를 저장할 때,UpdateModelMixin
에 의해 호출된다.
perform_destroy(self, instance)
- 인스턴스를 삭제할 때,DestroyModelMixin
에 의해 호출된다.
이러한 훅은 리퀘스트 ‘데이터의 일부’가 아닌 리퀘스트 ‘속성’을 설정하는 데 유용하다.
예를 들어, ‘리퀘스트 유저’ 또는 ‘URL 키워드 인수’를 이용해 객체의 속성을 설정할 수 있다.
(*훅은 ‘걸다’의 의미로 여기서는 ‘부가 설정’이라고 생각하자.)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
이러한 오버라이드 지점들은 객체를 저장하기 전, 후에 발생하는 동작을 추가하는 데 유용하다.
(예를들어 확인 이메일 발송, 업데이트 기록 )
def perform_update(self, serializer):
instance = serializer.save()
send_email_confirmation(user=self.request.user, modified=instance)
이러한 훅을 사용하여 ValidationError()
를 발생시켜 유효성 검사를 추가할 수도 있다.
이는 데이터베이스 저장 시점에 적용하면 유용하다. 예를 들어 :
def perform_create(self, serializer):
queryset = SignupRequest.objects.filter(user=self.request.user)
if queryset.exists():
raise ValidationError('You have already signed up')
serializer.save(user=self.request.user)
Other methods:
일반적으로 다음 메소드들은 오버라이드할 필요가 없지만 'GenericAPIView'를 사용하면서 커스텀을 하고 싶은 경우 불러올 수 있다.
get_serializer_context(self)
- serializer에 주어야 하는 추가 컨텍스트가 포함된 딕셔너리를 반환. 기본적으로 ''요청'', ''보기'' 및 ''형식'' 키를 포함한다.
get_serializer(self, instance=None, data=None, many=False, partial=False)
- serializer 인스턴스를 반환.
get_paginated_response(self, data)
- 페이지를 매긴 'Response' 객체를 반환.paginate_queryset(self, queryset)
- 필요한 경우 쿼리셋에 페이지를 매기고, 페이지 개체를 반환. 만약 이 뷰에 대해 페이지 나누기가 설정되지 않은 경우 'None'을 반환.filter_queryset(self, queryset)
- 쿼리셋을 넣으면 사용 중인 필터 백엔드로 필터링하여 새 쿼리셋을 반환.