Django Rest Frameworkの処理メモ

Django Rest Framework、使うたびに中を開けて同じことを調べているので、内部の主要なメソッドのメモを残す。

ViewSetMixin

class ViewSetMixin:
    request:
    args = args
    kwargs = kwargs
    action:Literal["list", "create", "get", "update", "partial_update", "destroy"]

Listの処理

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
        ]

Retrieveの処理

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)

Createの処理

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

Updateの処理

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)

Deteteの処理

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の悪い見本だと思う。

Amazon.co.jpアソシエイト: