Django Rest Framework 소스 해결 - 시리얼화된 역시리얼화

14834 단어 Django
Django Rest Framework 소스 해결 - 시리얼화된 역시리얼화
예시 코드는 백엔드에서 작성한 코드와 서열화 과정만 보여 줍니다. 예시 코드는 다음과 같습니다.
파일을 나누는 것이 귀찮아서 모두views를 씁니다.py가 맞았다
import re

from django.db import models

from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet


class UserProfile(models.Model):
    """
       
    """
    username = models.CharField(
        max_length=20, default="", verbose_name="  ", help_text="  ")
    email = models.EmailField(
        max_length=50, verbose_name="  ", help_text="  ")


class UserSerializer(serializers.ModelSerializer):
    """
         
    """
    class Meta:
        model = UserProfile
        fields = "__all__"


class UserViewSet(ModelViewSet):
    """
        :    
    """
    queryset = UserProfile.objects.all()
    serializer_class = UserSerializer

url.py
from django.contrib import admin
from django.urls import path, include

from study.views import UserViewSet
from rest_framework import routers

router = routers.SimpleRouter()
router.register(r"users", UserViewSet, base_name="users")

urlpatterns = [
    path('admin/', admin.site.urls),
    path(r"api/", include(router.urls))

1. 신규 사용자 Serializer의 서열화 과정
1. 서열화된 대상 가져오기
class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        #      
        #            data        ,instance       
        #             
        serializer = self.get_serializer(data=request.data)
        #     
        serializer.is_valid(raise_exception=True)
        #     
        self.perform_create(serializer)
        """
        def perform_create(self, serializer):
            serializer.save()
        """
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class GenericAPIView(views.APIView):
    .......
    serializer_class = None
    .......
    def get_serializer(self, *args, **kwargs):
        """
        Return the serializer instance that should be used for validating and
        deserializing input, and for serializing output.
        """
        #        
        serializer_class = self.get_serializer_class()
        kwargs['context'] = self.get_serializer_context()
        return serializer_class(*args, **kwargs)

    def get_serializer_class(self):
        """
        Return the class to use for the serializer.
        Defaults to using `self.serializer_class`.

        You may want to override this if you need to provide different
        serializations depending on the incoming request.

        (Eg. admins get full serialization, others get basic serialization)
        """
        assert self.serializer_class is not None, (
            "'%s' should either include a `serializer_class` attribute, "
            "or override the `get_serializer_class()` method."
            % self.__class__.__name__
        )
        #         Views   serializer_class = UserSerializer
        return self.serializer_class
    ......

이전 단계를 통해 우리는 Serializer =self를 알게 되었다.get_serializer (data=request.data) 가 실행하는 UserSerializer 클래스의 실례화, 데이터 파라미터를 전송하여 반서열화
2. Userializer 클래스의 실례화 과정
클래스 실례화 전에 new 방법을 실행합니다. 하나의 클래스의 생성 실례를 제어하는 과정에서 빈 대상을 생성하고, 하위 클래스가 없으면 부모 클래스의 new를 찾으며, new가 실행된 후에야 init 구조 방법을 실행할 수 있습니다.
User Serializer의 부류 Model Serializer에는 new 방법이 없고, Model Serializer의 부류 Serializer에도 new 방법이 없습니다. BaseSerlizer의 new 방법을 위로 찾으세요.
class BaseSerializer(Field):
    .......
    
    def __init__(self, instance=None, data=empty, **kwargs):
        self.instance = instance
        #    data      self.initial_data
        if data is not empty:
            self.initial_data = data
        self.partial = kwargs.pop('partial', False)
        self._context = kwargs.pop('context', {})
        kwargs.pop('many', None)
        super().__init__(**kwargs)

    def __new__(cls, *args, **kwargs):
        # We override this method in order to automagically create
        # `ListSerializer` classes instead when `many=True` is set.
        # many     False,             many_init
        if kwargs.pop('many', False):
            return cls.many_init(*args, **kwargs)
        #     Field new
        return super().__new__(cls, *args, **kwargs)

3. Userializer 클래스의 실례화 후 serializer를 실행한다.is_valid(raise exception=True) 메소드 검증 데이터
class BaseSerializer(Field):
    ......
    
    def is_valid(self, raise_exception=False):
        assert not hasattr(self, 'restore_object'), (
            'Serializer `%s.%s` has old-style version 2 `.restore_object()` '
            'that is no longer compatible with REST framework 3. '
            'Use the new-style `.create()` and `.update()` methods instead.' %
            (self.__class__.__module__, self.__class__.__name__)
        )

        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )

        if not hasattr(self, '_validated_data'):
            try:
                #          self.initial_data  
                #            data            self.initial_data
                self._validated_data = self.run_validation(self.initial_data)
            except ValidationError as exc:
                self._validated_data = {}
                self._errors = exc.detail
            else:
                self._errors = {}

        if self._errors and raise_exception:
            raise ValidationError(self.errors)

        return not bool(self._errors)
#       Field run_validation  
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
    ......

    def run_validation(self, data=empty):
        """
        We override the default `run_validation`, because the validation
        performed by validators and the `.validate()` method should
        be coerced into an error dictionary with a 'non_fields_error' key.
        """
        #     
        (is_empty_value, data) = self.validate_empty_values(data)
        #      data
        if is_empty_value:
            return data
        #          OrderedDict()     
        value = self.to_internal_value(data)
        try:
            #      
            self.run_validators(value)
            #       
            value = self.validate(value)
            """
                              ,    ,                   
            def validate(self, attrs):
                return attrs
            """
            assert value is not None, '.validate() should return the validated data'
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=as_serializer_error(exc))

        return value
# self.validate_empty_values     
class Field:
    ......
    def get_default(self):
        """
                    ,              。
                      ,       “SkipField”,                      。
        """
        if self.default is empty or getattr(self.root, 'partial', False):
            # No default, or this is a partial update.
            raise SkipField()
        if callable(self.default):
            if hasattr(self.default, 'set_context'):
                self.default.set_context(self)
            return self.default()
        return self.default

    def validate_empty_values(self, data):
        """
        #     ,  :
        # *Raise “ValidationError”,      。
        # *Raise “SkipField”,          。
        # * Return (True, data),      ,                   。
        # *Return (False, data),       ,          。
        """
        #  self.get_default()      
        #        
        if self.read_only:
            return (True, self.get_default())

        if data is empty:
            #          
            if getattr(self.root, 'partial', False):
                raise SkipField()
            #       
            if self.required:
                self.fail('required')
            return (True, self.get_default())

        if data is None:
            #      null  
            if not self.allow_null:
                self.fail('null')
            #           ,        ' source='*' '  。    ' source='*' '             ,     null。
            elif self.source == '*':
                return (False, None)
            return (True, None)

        return (False, data)

국부 갈고리 검증self.to_internal_value(data)
#       Field to_internal_value  
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
    ......
    def to_internal_value(self, data):
        """
        Dict of native values 

4. 데이터 검증 후에 실행되는 것이 바로 Serializer이다.save () 방법
class BaseSerializer(Field):
    .......
    def save(self, **kwargs):
        assert not hasattr(self, 'save_object'), (
            'Serializer `%s.%s` has old-style version 2 `.save_object()` '
            'that is no longer compatible with REST framework 3. '
            'Use the new-style `.create()` and `.update()` methods instead.' %
            (self.__class__.__module__, self.__class__.__name__)
        )

        assert hasattr(self, '_errors'), (
            'You must call `.is_valid()` before calling `.save()`.'
        )

        assert not self.errors, (
            'You cannot call `.save()` on a serializer with invalid data.'
        )

        # Guard against incorrect use of `serializer.save(commit=False)`
        assert 'commit' not in kwargs, (
            "'commit' is not a valid keyword argument to the 'save()' method. "
            "If you need to access data before committing to the database then "
            "inspect 'serializer.validated_data' instead. "
            "You can also pass additional keyword arguments to 'save()' if you "
            "need to set extra attributes on the saved model instance. "
            "For example: 'serializer.save(owner=request.user)'.'"
        )

        assert not hasattr(self, '_data'), (
            "You cannot call `.save()` after accessing `serializer.data`."
            "If you need to access data before committing to the database then "
            "inspect 'serializer.validated_data' instead. "
        )

        validated_data = dict(
            list(self.validated_data.items()) +
            list(kwargs.items())
        )
        #              ,      (        update )
        if self.instance is not None:
            self.instance = self.update(self.instance, validated_data)
            assert self.instance is not None, (
                '`update()` did not return an object instance.'
            )
        else:
            #   create  
            self.instance = self.create(validated_data)
            assert self.instance is not None, (
                '`create()` did not return an object instance.'
            )

        return self.instance

self.create(validated_data)
#    BaseSerializer   create  
class ModelSerializer(Serializer):
    ......
    # Default `create` and `update` behavior...
    def create(self, validated_data):
        """
        We have a bit of extra checking around this in order to provide
        descriptive messages when something goes wrong, but this method is
        essentially just:

            return ExampleModel.objects.create(**validated_data)

        If there are many to many fields present on the instance then they
        cannot be set until the model is instantiated, in which case the
        implementation is like so:

            example_relationship = validated_data.pop('example_relationship')
            instance = ExampleModel.objects.create(**validated_data)
            instance.example_relationship = example_relationship
            return instance

        The default implementation also does not handle nested relationships.
        If you want to support writable nested relationships you'll need
        to write an explicit `.create()` method.
        """
        raise_errors_on_nested_writes('create', self, validated_data)

        ModelClass = self.Meta.model

        # Remove many-to-many relationships from validated_data.
        # They are not valid arguments to the default `.create()` method,
        # as they require that the instance has already been saved.
        info = model_meta.get_field_info(ModelClass)
        many_to_many = {}
        for field_name, relation_info in info.relations.items():
            if relation_info.to_many and (field_name in validated_data):
                many_to_many[field_name] = validated_data.pop(field_name)

        try:
            instance = ModelClass._default_manager.create(**validated_data)
        except TypeError:
            tb = traceback.format_exc()
            msg = (
                'Got a `TypeError` when calling `%s.%s.create()`. '
                'This may be because you have a writable field on the '
                'serializer class that is not a valid argument to '
                '`%s.%s.create()`. You may need to make the field '
                'read-only, or override the %s.create() method to handle '
                'this correctly.
Original exception was:
%s' % ( ModelClass.__name__, ModelClass._default_manager.name, ModelClass.__name__, ModelClass._default_manager.name, self.__class__.__name__, tb ) ) raise TypeError(msg) # Save many-to-many relationships after the instance is created. if many_to_many: for field_name, value in many_to_many.items(): field = getattr(instance, field_name) field.set(value) return instance

좋은 웹페이지 즐겨찾기