Django序列化组件Serializers使用详解

目录
  • 01、为什么要用序列化组件
  • 02、序列化组件的基本使用
  • 03、序列化组件常用字段
  • 04、序列化组件is_valid、validated_data
  • 05、序列化组件校验字段
  • 06、序列化组件.create() and .update()
  • 07、序列化组件ModelSerializer
  • 08、序列化组件构造复杂的结构
  • 09、序列化组件修改返回值to_representation、to_internal_value

本文主要系统性的讲解django rest framwork 序列化组件的使用,基本看完可以解决工作中序列化90%的问题,写作参考官方文档https://www.django-rest-framework.org/api-guide/serializers/#modelserializer,分成如下九个部分:

01、为什么要用序列化组件

我们知道前后端常用json数据结构交互, 在后端我们常想把一个对象返回给前端,但是json序列化是不能序列化对象(不过可以添加序列化参数encoder序列化原理和序列化组件差不多需要自己定义序列化类和返回的结构),所以就有了我们的序列化组件,可以自定义特定结构把对象序列化返回给前端,同时可以对前端传入的参数进行数据校验等功能。

02、序列化组件的基本使用

models

from django.db import models

# Create your models here.

class Book(models.Model):
    id = models.IntegerField(primary_key=True)
    title = models.CharField(max_length=255)
    desc = models.CharField(max_length=255)
    is_deleted = models.IntegerField(choices=[(1, "删除"), (0, "未删除")])
    author = models.CharField(max_length=255)

serializer

from rest_framework.serializers import Serializer
from rest_framework import serializers

class BookSerializer(Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField()
    desc = serializers.CharField()
    is_deleted = serializers.ChoiceField(choices=[(1, "删除"), (0, "未删除")], source="get_is_deleted_display")
    author = serializers.CharField()

views

from app01.models import Book
from app01.serializer import BookSerializer
from django.http import HttpResponse, JsonResponse

# Create your views here.

def get_books(request):
    books = Book.objects.all()
    se = BookSerializer(books, many=True)
    return JsonResponse(se.data, safe=False)

结果返回:

[{"id": 1, "title": "活着", "desc": "讲述一代人的人生", "is_deleted": "未删除", "author": "余华"}]

在写法上model和serializer的写法非常相近,但内在逻辑model是与数据库表的关系映射,serializer是对对象的序列化和反序列化。

03、序列化组件常用字段

常用字段类型

字段 字段构造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField UUIDField(format='hex_verbose')
format:
1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a"
3)'int' - 如: "123456789012312313134124512351145145114"
4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressField IPAddressField(protocol='both', unpack_ipv4=False, **options)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
max_digits: 最多位数
decimal_palces: 小数点位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices)
choices与Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

选项参数:

名称 作用
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最大值
min_value 最小值

通用参数

参数名称 说明
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息

在这里额外讲一个参数source,在官方文档中是这样解释的:

将用于填充字段的属性的名称。可以是仅接受self参数的方法,例如URLField(source='get_absolute_url'),也可以使用点分符号遍历属性,例如EmailField(source='user.email')。当使用点分符号序列化字段时,default如果在属性遍历期间任何对象不存在或为空,则可能需要提供一个值。

该值source='*'具有特殊含义,用于指示应将整个对象传递给该字段。这对于创建嵌套表示或对需要访问完整对象才能确定输出表示的字段很有用。

默认为字段名称。

  其中比较常用的用法:

  1、source="get_field_name_display"如上所展示,在choice字段中可以展示选项对应的解释,这中用法代表的是官方解释说的可以是仅接受self参数的方法,也就是source中可以填serializer对象可以调用的方法(方法中需要传入self),内在逻辑是这个字段会展示此方法的返回的结果。

  2、source='user.email'这种用法常在ModelSerializer的子类中,其中user为User对象,此中写法是指展示user的email属性,常用于我们想把外键对象user的属性和本对象的属性展示在同一层级,而不是下一级。

04、序列化组件is_valid、validated_data

  当我们定义好序列化器时,怎么校验传入的字段呢?那就是is_valid方法,可以根据定义序列化器的校验规则判断传入字段是否合法。

serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']}

然后serializer.validated_data就可以获取校验过后的数据字典。

05、序列化组件校验字段

序列化组件校验字段的方式常有三种:

1、首先是在字段的validators属性, 其中传入一个校验方法列表如:validators=(my_validator, )其中my_validator中定义校验规则。

def multiple_of_ten(value):
    if value % 10 != 0:
        raise serializers.ValidationError('Not a multiple of ten')

class GameRecord(serializers.Serializer):
    score = IntegerField(validators=[multiple_of_ten])

2、最常用的是定义一个validate_field_name(self, value)的函数(其中field_name指的是字段名),函数内是具体的逻辑。

from rest_framework import serializers

class BlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

    def validate_title(self, value):
        """
        Check that the blog post is about Django.
        """
        if 'django' not in value.lower():
            raise serializers.ValidationError("Blog post is not about Django")
        return value

3、最后一种是定义一个validate(self, data)其中data是所有字段的键值对,所以这个校验方法是对象级别的校验。

from rest_framework import serializers

class EventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

    def validate(self, data):
        """
        Check that start is before finish.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data

当然或许当你看到这里会问why?how? 只能说源码是最好的答案。

06、序列化组件.create() and .update()

  在我们定义的序列化类中, 可以添加create和update方法,当我们有需求是根据反序列化后的数据在数据库表中创建记录或者更新某条数据,这时我们就可以在create方法和update方法中定义对应的逻辑。

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
   def create(self, validated_data):
        return Comment.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        instance.save()
        return instance

  接下来调用serializer.save()命令便可创建一条纪录或者更新一条记录,其中判断save时什么时候是创建什么时候是更新呢?关键在于serializer的实例化。

# .save() will create a new instance.
serializer = CommentSerializer(data=data)
serializer.save()
# .save() will update the existing `comment` instance.
 serializer = CommentSerializer(comment, data=data)

serializer.save()

  其中当Serializer类实例化没有传入model对象时会调用create方法创建一条记录, 如果Serializer类实例化时传入了model对象就会调用update方法更新一条记录。

  有时除了反序列化的字段我们还需要其他字段怎么办呢?我们可以在save中传入参数名和值,可以在validated_data中根据参数名取到对应的值。

serializer.save(owner=request.user)

这样我们就可以在validated_data.get("owner")就可以取到user对象了。

07、序列化组件ModelSerializer

  ModelSerializer和表单的ModelForm组件很相似,都极大简化了我们的开发,可以在内部类Meta中定义对应的model,ModelSerializer就会自动生成model字段对应的Field不用我们定义。

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = Account
        fields = ['id', 'account_name', 'users', 'created']

   其中fields中定义序列化的字段,如果是全部字段就写__all__, 上述例子我们没有定义具体的字段,ModelSerializer帮我们自动生成了 'id', 'account_name', 'users', 'created'的Field。

08、序列化组件构造复杂的结构

  以下是个存在一对多和多对多字段的序列化器

serializer

from res_framework import serializers

#这个类用于被实例化,多对多字段这么写
class AuthorSerializer(serializers.Serializer):
    id = serializers.Charfield()
    name = serializers.Charfield()
    age = serializers.Charfield()

#传给views.py的主类
class BookSerializer(serializers.Serializer):
    name = serializers.Charfield()
    #source 可以指定字段 ,  id是要序列化的表名。
    id  = serializers.CharField(source='nid')
    #,source后字段用.的方式可以跨表查询。
    publish = serializer.CharField(source='publish.email')
    '''
    如果在models.py的book类中定义一个test方法。
    def test(self):
        return str(self.price)+self.name
   '''
   # 返回的结果就会有xx字段,souce不但可以指定表模型字段,还可以指定模型表方法,并且赋值给xx变量
   xx = serializers.Charfield(source='test')

   #外键的实现方法:
   #一对多字段
   #如果要通过外键字段返回出版社的所有信息,包括id,name,email...
   #obj是当前循环序列化到的数据对象
    publish = serializers.SerializerMethodField()
    def get_publish(self,obj):
        return {'id‘:obj.publish.pk,'name':obj.publish.name}

   #多对多字段
   #所有作者的详情,也展示出来
    authors = serializers.SerializermethodFiled()
    def get_authors(self,obj):
        author_list  = obj.authors.all()
        author_ser = AuthorSerializer(author_list,many=True)
        return author_ser.data

views

from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import models

class BookView(APIview):
    def get(self,request,*args,**kwargs):
            #获取所有图书数据
        response = {'status':100,'msg':'获取成功'}
        book_list = models.Book.objects.all()
        #实例化BookSerializer类,把要序列化的数据book_list传入
        #如果要序列化querySet对象,一定要加many = True
        book_ser = BookSerializer(book_list,many=True)
        #把序列化后的数据book_ser.data 拿出来放到response字典中返回给客户端
        response['data'] = book_ser.data
        return Response(response)

如果使用ModelSerializer:

serializer

from app01 import models
class PublishSerializer(serializers.ModelSerializer):
    class Meta: #固定写法
    # 指定要序列化Book表
    model = models.Book
    #指定要序列化的字段
    fields = ['nid','name']
    #序列化所有字段
    fileds ='__all__‘
    #要排除的字段(不能与fileds连用)
    # exclude = ['name','price']
    #深度判定
    depth = 1
    #如果要不按照父类的来,想要自己定义显示的字段的话,自己定义一个,覆盖掉父类的字段属性。
    publish = serializers.SerializerMethodField()  #一对多字段
    def get_publish(self,obj):
        return {'id‘:obj.publish.pk,'name':obj.publish.name}

  这里额外解释一下depth这个参数:在对象外键另一对象,另一对象又外键另一对象以此类推,depth的作用就是可以决定序列化时的外键深度。

  复杂序列化器的要点在于,serializers.SerializerMethodField()和get_field_name的使用获取自己想得到的字段值,还有source的使用,上面有讲。

09、序列化组件修改返回值to_representation、to_internal_value

  to_representation(self, instance):如果序列化器定义了此方法,可以改变序列化对象data的值,也就是serializer.data的值,你可以根据自己的业务场景去重新构造返回值。

def to_representation(self, instance):
    """Convert `username` to lowercase."""
    ret = super().to_representation(instance)
    ret['username'] = ret['username'].lower()
    return ret

  to_internal_value(self, data): data为未经校验的数据字段, 此方法可以实现校验和修改反序列化后的值,然后返回。如果不想修改反序列化后的值只是做校验的话,完全可以使用validate方法替代。

def to_internal_value(self, value):
    if value == None:
        return 0
    return value

  总而言之,这两个方法一个是用于重新构造validated_data并返回,一个用于重新构造serializer.data的值并返回。

到此这篇关于Django序列化组件Serializers使用详解的文章就介绍到这了,更多相关Django序列化组件Serializers内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • django序列化serializers过程解析

    这篇文章主要介绍了django序列化serializers过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 DRF的核心 就是 前后端分离的核心 前后端分离开发的核心: 将模型转换为json 称之为 序列化 将json转换为模型 称之为 反序列化 Django的序列化工具让你可以将Django的模型'翻译'成其它格式的数据.通常情况下,这种其它格式的数据是基于文本的,并且用于数据交换\传输过程. 序列化数据 Django为我们提供了一个强

  • django自带serializers序列化返回指定字段的方法

    django orm 有个defer方法,指定模型排除的字段. 如下返回的Queryset, 排除'username', 'id'. users=models.UserInfo.objects.defer('username','id') 或users=models.UserInfo.objects.filter(...).defer('username','id') 再如下,使用django自带serializers进行序列,发现序列化的数据仍存在'username', 'id'这两个字段.

  • django rest framework serializers序列化实例

    serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用: - 将queryset与model实例等进行序列化,转化成json格式,返回给用户(api接口). - 将post与patch/put的上来的数据进行验证. - 对post与patch/put数据进行处理. 实现序列化二个类:Serializer与ModelSerializer 比较 ModelSerializer(Serializer) 即 ModelSerializer继承了Se

  • Django序列化组件Serializers使用详解

    目录 01.为什么要用序列化组件 02.序列化组件的基本使用 03.序列化组件常用字段 04.序列化组件is_valid.validated_data 05.序列化组件校验字段 06.序列化组件.create() and .update() 07.序列化组件ModelSerializer 08.序列化组件构造复杂的结构 09.序列化组件修改返回值to_representation.to_internal_value 本文主要系统性的讲解django rest framwork 序列化组件的使用,

  • django admin组件使用方法详解

    关于admin: (1) admin的概述: admin是一个django子代的组件,当创建一个项目会后,就会在settings文件的 INSTALLED_APPS 中自动注册,另外在urls.py 文件中同样存在admin的路由 INSTALLED_APPS = [ #自带并且注册的一个组件即app 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', urlpatterns = [ # 自动

  • Django ModelForm组件使用方法详解

    一.创建ModelForm from django.forms import ModelForm from appxx import models from django.forms import widgets as wdt # 因为重名,所以起个别名 #定义一个类,比如BookForm,这个类要继承ModelForm,在这个类中再写一个原类Meta(规定写法,注意首字母是大写的) #在这个原类中,有以下属性(部分): class BookForm(ModelForm): class Meta

  • 对django layer弹窗组件的使用详解

    父层: <div class="col-xs-12"> <div class="box"> <div class="box-header"> <h3 class="box-title">主机监控列表</h3> </div> <!-- /.box-header --> <div class="box-body" styl

  • Java 序列化和反序列化实例详解

    Java 序列化和反序列化实例详解 在分布式应用中,对象只有经过序列化才能在各个分布式组件之间传输,这就涉及到两个方面的技术-发送者将对象序列化,接受者将对象反序列化,下面就是一个很好的例子! 1.实体-Employee import java.io.Serializable; public class Employee implements Serializable{ /** * */ private static final long serialVersionUID = 1L; publi

  • 在django中自定义字段Field详解

    Django的Field类中方法有: to_python() # 把数据库数据转成python数据 from_db_value() # 把数据库数据转成python数据 get_pre_value() # 把python数据压缩准备存入数据库 get_db_pre_value() # 把压缩好的数据转成数据库查询集 get_prep_lookup() # 指定过滤的条件 value_to_string() # 数据序列化 如果创建的Field比字符串,日期,整数等更复杂的数据结构,可能需要重写t

  • Django REST Framework 分页(Pagination)详解

    在前面的DRF系列教程中,我们以博客为例介绍了序列化器, 使用基于类的视图APIView和ModelViewSet开发了针对文章资源进行增删查改的完整API端点,并详细对权限和认证(含jwt认证)进行了总结与演示.在本篇文章中我们将向你演示如何在Django REST Framework中使用分页. 分页 为什么要分页? 当你的数据库数据量非常大时,如果一次将这些数据查询出来, 必然加大了服务器内存的负载,降低了系统的运行速度.一种更好的方式是将数据分段展示给用户.如果用户在展示的分段数据中没有

  • Angular2 组件交互实例详解

    1. 组件通信 我们知道Angular2应用程序实际上是有很多父子组价组成的组件树,因此,了解组件之间如何通信,特别是父子组件之间,对编写Angular2应用程序具有十分重要的意义,通常来讲,组件之间的交互方式主要有如下几种: l 使用输入型绑定,把数据从父组件传到子组件 l 通过 setter 拦截输入属性值的变化 l 使用 ngOnChanges 拦截输入属性值的变化 l 父组件监听子组件的事件 l 父组件与子组件通过本地变量互动 l 父组件调用 ViewChild l 父组件和子组件通过服

  • django基础之数据库操作方法(详解)

    Django 自称是"最适合开发有限期的完美WEB框架".本文参考<Django web开发指南>,快速搭建一个blog 出来,在中间涉及诸多知识点,这里不会详细说明,如果你是第一次接触Django ,本文会让你在感性上对Django有个认识,完成本文操作后会让你有兴趣阅读的相关书籍和文档. 本文客操作的环境,如无特别说明,后续都以下面的环境为基础: =================== Windows 7/10 python 3.5 Django 1.10 ======

  • 微信小程序组件 marquee实例详解

    微信小程序组件 marquee实例详解 1. marquee标签 html是有marquee标签的,可以实现跑马灯效果,但小程序没有,所以要实现.这里考虑使用css3的animation实现. html的marquee是这样使用的. <marquee direction="left" behavior="scroll" scrollamount="1" scrolldelay="0" loop="-1"

随机推荐