class BaseSerializer(Field)

"""
The BaseSerializer class provides a minimal class which may be used
for writing custom serializer implementations.
这个类提供一个最小化的类,可以用来写自定义的序列化实现 Note that we strongly restrict the ordering of operations/properties
that may be used on the serializer in order to enforce correct usage.
序列化上会用到的操作/属性的顺序是被限制的,为了正确的使用 In particular, if a `data=` argument is passed then:
如果传递data=这个参数 .is_valid() - Available.可用
.initial_data - Available.可用
.validated_data - Only available after calling `is_valid()`调用is_valid之后可用
.errors - Only available after calling `is_valid()`
.data - Only available after calling `is_valid()` If a `data=` argument is not passed then:
一般来水不会传递data这个参数
.is_valid() - Not available.
.initial_data - Not available.
.validated_data - Not available.
.errors - Not available.
.data - Available.
"""

  

    def __init__(self, instance=None, data=empty, **kwargs):    #初始化,传入instance参数(一个model class的实例)
self.instance = instance #instance给到self
if data is not empty:
self.initial_data = data
self.partial = kwargs.pop('partial', False) #将额外的字典参数中,partial,context给到self,如果没有,给出默认值
self._context = kwargs.pop('context', {})
kwargs.pop('many', None) #将many这个key删除
super().__init__(**kwargs) #继承父类的其余属性

  

    # 对self.data属性函数化,为了加判断
# 将instance转化为data
@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.'
)
raise AssertionError(msg) if not hasattr(self, '_data'):
if self.instance is not None and not getattr(self, '_errors', None):
self._data = self.to_representation(self.instance)
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data

  


class Serializer(BaseSerializer, metaclass=SerializerMetaclass):

    # 继承父类的data属性,然后调用ReturnDict函数返回
@property
def data(self):
ret = super().data
return ReturnDict(ret, serializer=self)

  

app目录

serializer.py

# 创建serializers.Serializer的子类
# 几个field是Fields.py里Field的几个子类
class ColorsSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
colors = serializers.CharField(max_length=10)
def create(self, validated_data):
return Colors.objects.create(**validated_data) def update(self, instance, validated_data):
instance.colors = validated_data.get('colors', instance.colors)
instance.save()
return instance

views.py

def test(request):
color = Colors(id=2,colors='red') #color为一个xxx.models.Colors的instance
print(color) #一个instance,由该model类的__str__(self)的返回值决定
serializer = ColorsSerializer(instance=color) #将这个instance传入序列化类,返回一个序列化实例
print(serializer.data) # <class 'rest_framework.utils.serializer_helpers.ReturnDict'>
print(type(serializer.data)) # {'id': 2, 'colors': 'red'}
return HttpResponse('done')

  

class ModelSerializer(Serializer):

    """
A `ModelSerializer` is just a regular `Serializer`, except that: * A set of default fields are automatically populated.
* A set of default validators are automatically populated.
* Default `.create()` and `.update()` implementations are provided.
*将自动填充一组默认字段。
*将自动填充一组默认验证器。
*提供了默认的`.create()`和`.update()`实现。elds
The process of automatically determining a set of serializer fields
based on the model fields is reasonably complex, but you almost certainly
don't need to dig into the implementation. If the `ModelSerializer` class *doesn't* generate the set of fields that
you need you should either declare the extra/differing fields explicitly on
the serializer class, or simply use a `Serializer` class.
如果“modelserializer”class没有生成所需字段,我应该在序列化类明确申明额外字段
或者直接使用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:
如果实例中有多对对字段,需要以下实现:先把字段从validated_data pop出来,
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) # 在Meta嵌套类中的model属性
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.
# 把model类的字段信息给到info
# 处理多对多字段
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)
# 表插入,返回到instance
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.\nOriginal exception was:\n %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

  

    # 在instance上设定每个属性,然后save
def update(self, instance, validated_data):
raise_errors_on_nested_writes('update', self, validated_data)
info = model_meta.get_field_info(instance) # Simply set each attribute on the instance, and then save it.
# Note that unlike `.create()` we don't need to treat many-to-many
# relationships as being a special case. During updates we already
# have an instance pk for the relationships to be associated with.
m2m_fields = []
for attr, value in validated_data.items():
if attr in info.relations and info.relations[attr].to_many:
m2m_fields.append((attr, value))
else:
setattr(instance, attr, value) instance.save() # Note that many-to-many fields are set after updating instance.
# Setting m2m fields triggers signals which could potentialy change
# updated instance and we do not want it to collide with .update()
for attr, value in m2m_fields:
field = getattr(instance, attr)
field.set(value) return instance # Determine the fields to apply...

  

app目录

serializers.py

class ColorsSerializer(serializers.ModelSerializer):
class Meta:
model = Colors
fields = ('url', 'id', 'colors')

  

views.py

def test(request):
color = Colors(id=2,colors='red')
print(color)
serializer = ColorsSerializer(instance=color,context={'request': request})
print(serializer.data)
print(type(serializer.data))
return HttpResponse('done')

  

几种多表操作的field应用

读取外键的某个字段

# Clothes的color是外键,默认情况下,color字段会对应母表的主键,id。
# 使用SlugRelatedField可以指向外键,slug_field表示获取哪个字段返回给color
# 这里color这个属性就被重写了
class ClothesSerializer(serializers.ModelSerializer):
color = serializers.SlugRelatedField(queryset=Colors.objects.all(), slug_field='colors_cn')
class Meta:
model = Clothes
fields = ('url', 'id', 'color', 'desc')

  

DRF源码-serializers的更多相关文章

  1. Django之DRF源码分析(二)---数据校验部分

    Django之DRF源码分析(二)---数据校验部分 is_valid() 源码 def is_valid(self, raise_exception=False): assert not hasat ...

  2. [drf]源码和序列化梳理

    drf源码继承管理 # drf继承关系 View APIView as_view: 执行父类的as_view 调用dispatch dispatch init_request request.quer ...

  3. 02 drf源码剖析之快速了解drf

    02 drf源码剖析之快速了解drf 目录 02 drf源码剖析之快速了解drf 1. 什么是drf 2. 安装 3. 使用 3. DRF的应用场景 1. 什么是drf drf是一个基于django开 ...

  4. Django与drf 源码视图解析

    0902自我总结 Django 与drf 源码视图解析 一.原生Django CBV 源码分析:View """ 1)as_view()是入口,得到view函数地址 2) ...

  5. drf源码save以及response

    drf源码save以及response 一.save 其中蛮重要的一段 if self.instance is not None: self.instance = self.update(self.i ...

  6. DRF源码系列分析

    DRF源码系列分析 DRF源码系列分析--版本 DRF源码系列分析--认证 DRF源码系列分析--权限 DRF源码系列分析--节流

  7. drf源码剖析系列(系列目录)

    drf源码剖析系列(系列目录) 01 drf源码剖析之restful规范 02 drf源码剖析之快速了解drf 03 drf源码剖析之视图 04 drf源码剖析之版本 05 drf源码剖析之认证 06 ...

  8. 07 drf源码剖析之节流

    07 drf源码剖析之节流 目录 07 drf源码剖析之节流 1. 节流简述 2. 节流使用 3. 源码剖析 总结: 1. 节流简述 节流类似于权限,它确定是否应授权请求.节流指示临时状态,并用于控制 ...

  9. 06 drf源码剖析之权限

    06 drf源码剖析之权限 目录 06 drf源码剖析之权限 1. 权限简述 2. 权限使用 3.源码剖析 4. 总结 1. 权限简述 权限与身份验证和限制一起,决定了是否应授予请求访问权限. 权限检 ...

随机推荐

  1. Plcsim 模拟IO访问故障 OB122组织块

    假设在OB1 中用 如下指令 T PQW20 实际在组态的时候就没有QW20 这个地址 所以会显示访问IO 错误 我在OB122 中设置一个变量 进入一次 加1 可以看到每个扫描周期都要调用一次OB1 ...

  2. linux systemctl命令

    转自systemctl详解 systemctl 是系统服务管理器命令,它实际上将 service 和 chkconfig 这两个命令组合到一起. 任务 旧指令 新指令 使某服务自动启动 chkconf ...

  3. 解题报告:luogu P2678 跳石头

    题目链接:P2678 跳石头 很简单的二分查找,可悲的是我并不会. 不过题解贴心的写得很清楚(学会了套路) 二分一次判断一次,复杂度是\(O(nlogl)\),可以通过此题. \(Code:\) #i ...

  4. 数据库-----catalog与schema简介

    在SQL环境下Catalog和Schema都属于抽象概念,主要用来解决命名冲突问题 一个数据库系统包含多个Catalog,每个Catalog包含多个Schema,每个Schema包含多个数据库对象(表 ...

  5. 偶然在博客中见对百度一个面试题的探讨,写些自己的看法以及指出探讨中不对的观点:百度面试题:求绝对值最小的数 有一个已经排序的数组(升序),数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现 例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4。

    今天申请了博客园账号,在下班后阅览博客时发现了一个关于百度面试题探讨的博客(其实是个很基础的问题),此博客url为:http://www.blogjava.net/nokiaguy/archive/2 ...

  6. POJ 2309:BST lowbit

    BST Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9140   Accepted: 5580 Description C ...

  7. PYTHON画三维图

    import matplotlib.pyplot as pltfrom mpl_toolkits.mplot3d import Axes3Dimport numpy as np #bbb=[1 if ...

  8. linux下安装redis,按照redis官网安装不成功需要提前安装c++环境(安装成功并可以测试)

    这个安装是一种便捷的安装,没有几句,但是完全按照官网上的来没有安装成功,有前提条件的 打开linux root登录 然后在usr下面建文件夹redis,进入 在该文件加下,直接按照官网的指导进行安装即 ...

  9. 5 —— node —— 响应一段中文给客户端

    const http = require('http'); const server = http.createServer(); server.on('request',function(req,r ...

  10. TensorFlow2 Part2:基础知识回顾

    python面向对象编程回顾 基础概念: 面向对象的编程简称OOP,它把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向对象的设计思想是抽象出Class,根据Class(类)创建In ...