Django Rest Framework、使うたびに中を開けて同じことを調べているので、内部の主要なメソッドのメモを残す。
class ViewSetMixin:
request:
args = args
kwargs = kwargs
action:Literal["list", "create", "get", "update", "partial_update", "destroy"]
class ModelViewSet:
def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
class ListSerializer:
def to_representation(self, data):
iterable = data.all() if isinstance(data, models.Manager) else data
return [
self.child.to_representation(item) for item in iterable
]
class ModelViewSet:
def get_object(self):
queryset = self.filter_queryset(self.get_queryset())
# Perform the lookup filtering.
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs)
# May raise a permission denied
self.check_object_permissions(self.request, obj)
return obj
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
class ModelViewSet:
def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
def perform_create():
return serializer.save()
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class ModelSerializer:
def run_validation(data):
value = self.to_internal_value(data)
self.run_validators(value)
self.validate(value)
def is_valid(self):
self._validated_data = self.run_validation(self.initial_data)
def create(self, validated_data):
return model.object.create(validated_data)
def save(**kwargs):
self.instance = self.create(self.validated_data + kwargs)
@property
def data(self):
self._data = self.to_representation(self.instance)
return self._data
class ModelViewSet:
def perform_update(self, serializer):
serializer.save()
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
class ModelSerializer:
def update(self, instance, validated_data):
...
instance.save()
def save(self, **kwargs):
self.instance = self.update(self.validated_data + kwargs)
class ModelViewSet:
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
DRFを見るたびに思うけど、この設計は良くない。
ViewとSerializerにCreate/Retrieve/Update/Destroy/List全部の役割を押し込んでしまっていて、非常にわかりにくいし使いにくい。設定も難しい。それぞれのメソッドで全く異なる状態を保持しているのに、同じ data
というプロパティに押し込んでしまっているなど、いろいろ無理がある。大量のmixinで機能を継ぎ接ぎしているので、どこで何をやってるのかわかりにくい。OOPの悪い見本だと思う。
Copyright © 2020 Atsuo Ishimoto
Powered by miyadaiku