示例代码就只展示了后端编写的代码和序列化过程,示例代码如下:
懒得分文件就全部写再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))
一、查看用户列表Serializer的序列化过程
1、获取序列化对象
class ListModelMixin:
"""
List a queryset.
"""
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)
# 获取序列化对象
# 这里面的传参要说明一点data有值就是反序列化,instance有值就是序列化
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
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(queryset, many=True) 执行的UserSerializer类的实例化
2、UserSerializer类的实例化的过程
类实例化之前会执行new方法,用于控制一个类的生成实例的过程生成一个空对象,子类没有的就去找父类的new, new 执行完以后才能执行init构造方法
UserSerializer的父类ModelSerializer没有new方法,ModelSerializer的父类Serializer也没有new方法,在往上找BaseSerlizer中的new方法
class BaseSerializer(Field):
.......
def __init__(self, instance=None, data=empty, **kwargs):
self.instance = instance
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=True,执行cls.many_init(*args, **kwargs)
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
return super().__new__(cls, *args, **kwargs)
@classmethod
def many_init(cls, *args, **kwargs):
"""
This method implements the creation of a `ListSerializer` parent
class when `many=True` is used. You can customize it if you need to
control which keyword arguments are passed to the parent, and
which are passed to the child.
Note that we're over-cautious in passing most arguments to both parent
and child classes in order to try to cover the general case. If you're
overriding this method you'll probably want something much simpler, eg:
@classmethod
def many_init(cls, *args, **kwargs):
kwargs['child'] = cls()
return CustomListSerializer(*args, **kwargs)
"""
allow_empty = kwargs.pop('allow_empty', None)
child_serializer = cls(*args, **kwargs)
list_kwargs = {
'child': child_serializer,
}
if allow_empty is not None:
list_kwargs['allow_empty'] = allow_empty
list_kwargs.update({
key: value for key, value in kwargs.items()
if key in LIST_SERIALIZER_KWARGS
})
meta = getattr(cls, 'Meta', None)
# 调用ListSerializer
list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
return list_serializer_class(*args, **list_kwargs)
# 后面就是执行各个类的init构造方法
3、UserSerializer类的实例化后执行return Response(serializer.data)
class ListSerializer(BaseSerializer):
......
@property
def data(self):
# 执行父类的data
ret = super().data
return ReturnList(ret, serializer=self)
class BaseSerializer(Field):
......
@property
def data(self):
if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
msg = (
'When a serializer is passed a `data` keyword argument you '
'must call `.is_valid()` before attempting to access the '
'serialized `.data` representation.\n'
'You should either call `.is_valid()` first, '
'or access `.initial_data` instead.'
)
# 如果要访问data属性必须先调用is_valid方法进行检查
raise AssertionError(msg)
# 如果没有_data属性
if not hasattr(self, '_data'):
# 实例不为空并且没有_errors属性
if self.instance is not None and not getattr(self, '_errors', None):
self._data = self.to_representation(self.instance)
# 如果有is_valid后的数据并没有检查出错误则调用to_representation处理
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
self._data = self.to_representation(self.validated_data)
else:
# 如果都不符合则调用get_initial处理
self._data = self.get_initial()
return self._data
4、由于我们传入的instance,在执行self.to_representation函数时,就传入了instance实例
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
.......
def to_representation(self, instance):
"""
Object instance -> Dict of primitive datatypes.
"""
ret = OrderedDict()
# 获取可读的字段
fields = self._readable_fields
for field in fields:
try:
# 获取实例中对应的field字段
attribute = field.get_attribute(instance)
except SkipField:
continue
# We skip `to_representation` for `None` values so that fields do
# not have to explicitly deal with that case.
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
# 如果为空
if check_for_none is None:
# 则为空
ret[field.field_name] = None
else:
# 否则调用field的to_representation来处理attribute
ret[field.field_name] = field.to_representation(attribute)
return ret
@property
def _readable_fields(self):
# 在初始化的时候就获取只读的字段值
for field in self.fields.values():
if not field.write_only:
yield field
@cached_property
def fields(self):
"""
A dictionary of {field_name: field_instance}.
"""
# `fields` is evaluated lazily. We do this to ensure that we don't
# have issues importing modules that use ModelSerializers as fields,
# even if Django's app-loading stage has not yet run.
fields = BindingDict(self)
# 调用get_fields获取字段属性值
for key, value in self.get_fields().items():
# 写入该值
fields[key] = value
# 返回该字段
return fields
class ModelSerializer(Serializer):
......
def get_fields(self):
"""
Return the dict of field names -> field instances that should be
used for `self.fields` when instantiating the serializer.
"""
# 检查url_field_name
if self.url_field_name is None:
self.url_field_name = api_settings.URL_FIELD_NAME
# 必须配置Meta属性
assert hasattr(self, 'Meta'), (
'Class {serializer_class} missing "Meta" attribute'.format(
serializer_class=self.__class__.__name__
)
)
# 必须在Meta中配置model属性
assert hasattr(self.Meta, 'model'), (
'Class {serializer_class} missing "Meta.model" attribute'.format(
serializer_class=self.__class__.__name__
)
)
# 如果是抽象则直接报错
if model_meta.is_abstract_model(self.Meta.model):
raise ValueError(
'Cannot use ModelSerializer with Abstract Models.'
)
# 深拷贝所有字段
declared_fields = copy.deepcopy(self._declared_fields)
# 获取model
model = getattr(self.Meta, 'model')
# 获取深度信息
depth = getattr(self.Meta, 'depth', 0)
# 深度必须大于等于0小于等于10
if depth is not None:
assert depth >= 0, "'depth' may not be negative."
assert depth <= 10, "'depth' may not be greater than 10."
# Retrieve metadata about fields & relationships on the model class.
# 获取model的信息
info = model_meta.get_field_info(model)
# 获取filed字段名称
field_names = self.get_field_names(declared_fields, info)
# Determine any extra field arguments and hidden fields that
# should be included
# 获取额外参数
extra_kwargs = self.get_extra_kwargs()
extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(
field_names, declared_fields, extra_kwargs
)
# Determine the fields that should be included on the serializer.
fields = OrderedDict()
# 遍历字段名称
for field_name in field_names:
# If the field is explicitly declared on the class then use that.
# 如果在初始化的字段中
if field_name in declared_fields:
# 直接设置比进行下一个
fields[field_name] = declared_fields[field_name]
continue
# 获取额外定义的字段
extra_field_kwargs = extra_kwargs.get(field_name, {})
source = extra_field_kwargs.get('source', '*')
if source == '*':
source = field_name
# Determine the serializer field class and keyword arguments.
# 确定序列化器字段类和关键字参数
field_class, field_kwargs = self.build_field(
source, info, model, depth
)
# Include any kwargs defined in `Meta.extra_kwargs`
field_kwargs = self.include_extra_kwargs(
field_kwargs, extra_field_kwargs
)
# Create the serializer field.
# 创建额外字段的field实例
fields[field_name] = field_class(**field_kwargs)
# Add in any hidden fields.
fields.update(hidden_fields)
return fields
此时就通过Model转换成了序列化中渲染的字段值,在获取属性的过程中,其中filed.get_attribute方法,其实就是调用了如下方法;
def get_attribute(instance, attrs):
"""
Similar to Python's built in `getattr(instance, attr)`,
but takes a list of nested attributes, instead of a single attribute.
Also accepts either attribute lookup on objects or dictionary lookups.
"""
# 遍历属性列表
for attr in attrs:
try:
# 检查是否为Mapping
if isinstance(instance, Mapping):
# 直接获取属性
instance = instance[attr]
else:
# 直接获取实例的该属性
instance = getattr(instance, attr)
except ObjectDoesNotExist:
return None
if is_simple_callable(instance):
try:
instance = instance()
except (AttributeError, KeyError) as exc:
# If we raised an Attribute or KeyError here it'd get treated
# as an omitted field in `Field.get_attribute()`. Instead we
# raise a ValueError to ensure the exception is not masked.
raise ValueError('Exception raised in callable attribute "{}"; original exception was: {}'.format(attr, exc))
return instance