Django Rest Framework 소스 해결 - 시리얼화된 역시리얼화
14834 단어 Django
예시 코드는 백엔드에서 작성한 코드와 서열화 과정만 보여 줍니다. 예시 코드는 다음과 같습니다.
파일을 나누는 것이 귀찮아서 모두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
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Django 라우팅 계층 URLconf 작용 및 원리 해석URL 구성(URLconf)은 Django가 지원하는 웹 사이트의 디렉토리와 같습니다.그것의 본질은 URL과 이 URL을 호출할 보기 함수 사이의 맵표입니다. 위의 예제에서는 URL의 값을 캡처하고 위치 매개 변수로...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.