drf序列化器serializer的具体使用

目录
  • 一、序列化器-serializer
  • 二、序列化器的使用
    • 简单使用
  • 高级使用
    • source
    • **SerializerMethodField( ) **
    • 通用参数
  • 三、反序列化数据校验
    • 字段属性
    • 局部钩子
    • 全局钩子
    • validators
  • 四、序列化器操作数据
    • 查询所有
    • 查询单条
    • 新增数据
    • 修改数据
    • 删除数据
  • 五、模型类序列化器
  • 六、源码分析many=True

一、序列化器-serializer

  • 序列化,序列化器会把模型对象转成字典,经过response以后变成JSON字符串
  • 反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
  • 反序列化:完成数据校验功能

二、序列化器的使用

序列化器的使用分为两个阶段:

  • 在客户端请求时,使用序列化器可以完成对数据的反序列化。
  • 在服务器响应时,使用序列化器可以完成对数据的序列化。

简单使用

1、创建一个表模型

from django.db import models

class Books(models.Model):
    title = models.CharField(verbose_name='书名', max_length=32)
    publish = models.CharField(verbose_name='出版社', max_length=32)
    price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2)

2、新建一个py文件,写一个序列化的类,继承Serializer

3、在类中写要序列化的字段,想序列化那个字段,就在类中写那个字段

from rest_framework import serializers

class BooksSerializer(serializers.Serializer):
    title = serializers.CharField()
    publish = serializers.CharField()
    price = serializers.DecimalField()

4、在视图类中使用,导入——》实例化得到序列化对象,把要序列化的对象传入

5、序列化的对象.data——》是一个字典

6、把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse

from rest_framework.views import APIView
from rest_framework.request import Request
from app01.models import Books
from app01.ser import BooksSerializer

class BookView(APIView):
    def get(self, request, pk):
        # 响应信息
        response_msg = {'status': 200, 'message': '查询成功'}
        # 获取要序列化的对象
        book = Books.objects.filter(pk=pk).first()
        # 要序列化谁就把谁传到序列化类去
        book_ser = BooksSerializer(book)
        # book_ser.data————》序列化对象.data————》就是序列化后的字典
        # 将查询结果添加到响应信息内
        response_msg['data'] = book_ser.data
        return Response(response_msg)

 # urls.py
re_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),

7、如果要被序列化的是包含多条数据的查询集queryset,可以通过添加many=True参数

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.models import Books
from app01.ser import BooksSerializer

class BooksView(APIView):
    def get(self, request):
        # 响应信息
        response_msg = {'status': 200, 'message': '查询成功'}
        books = Books.objects.all()
        # 要序列化谁就把谁传到序列化类去
        book_ser = BooksSerializer(books, many=True)
        # book_ser.data————》序列化对象.data————》就是序列化后的字典
        # 将查询结果添加到响应信息内
        response_msg['data'] = book_ser.data
        return Response(response_msg)

# urls.py
re_path(r'^books/', views.BookView.as_view()),

高级使用

source

1、可以修改字段名字

class BooksSerializer(serializers.Serializer):
    xxx = serializers.CharField(source='title')  # 相当于——》xxx = Books.title

# 响应
{
    "status": 200,
    "message": "查询成功",
    "data": {
        "xxx": "魔道祖师"   ————》响应的字段名被修改了
    }
}

2、可以跨表查询

class BookSerializer(serializers.Serializer):
    publish_email = serializers.CharField(source='publish.email')
    # 相当于——》publish_email = Book.publish.email 连表查询publish表的email字段

# 响应
{
    "status": 200,
    "message": "查询成功",
    "data": {
        "publish_email": "modao@163.com"
    }
}

3、可以执行方法

# models.py
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.IntegerField()
    pub_date = models.DateTimeField()
    publish = models.ForeignKey("Publish", on_delete=models.CASCADE, null=True)
    authors = models.ManyToManyField("Author")

    def func(self):
        return '666666'

# ser.py
class BookSerializer(serializers.Serializer):
    msg = serializers.CharField(source='func')
    # msg = Book.func  ——》调用Book类中的func()方法的返回值

# 响应
{
    "status": 200,
    "message": "查询成功",
    "data": {
        "msg": "666666"
    }
}

**SerializerMethodField( ) **

它需要有一个配套的方法,方法名叫做get_字段名,返回值就是要显示的东西

class BookSerializer(serializers.Serializer):
    authors = serializers.SerializerMethodField()

    def get_authors(self, instance):
        # instance ——》 Book对象
        authors = instance.authors.all()    # 取出所有作者
        author_list = []
        for author in authors:
            author_list.append({'name': author.name, 'age': author.age})
        return author_list

通用参数

read_only:(只读)表明该字段仅用于序列化输出,默认False,如果设置成True,响应中可以看到该字段,修改时,不需要传该字段

write_only:(只写)表明该字段仅用于反序列化输入,默认False,如果设置成True,响应中看不到该字段,修改时,该字段需要传

from rest_framework import serializers

class BooksSerializer(serializers.Serializer):
    title = serializers.CharField(read_only = True)  # 响应中能看到改字段,修改不需要传值
    publish = serializers.CharField(write_only = True) # 响应中看不到改字段,修改需要传值
    price = serializers.DecimalField()

还有参数如下:

  • required  表明该字段在反序列化时必须输入,默认True
  • default   反序列化时使用的默认值
  • allow_null  表明该字段是否允许传入None,默认False
  • validators  该字段使用的验证器
  • error_messages 包含错误编号与错误信息的字典

三、反序列化数据校验

当使用序列化器对数据进行反序列化时,就需要对数据进行校验了,只有校验成功的数据才能被保存成模型类对象

将要校验的数据传入序列化器中并实例化:obj = BooksSerializer(data=request.data),调用is_valid()方法校验,校验成功返回True,失败返回False。

失败,可以通过序列化器对象的errors获取错误信息(字典)

成功,可以公共序列化对象的validated_data属性获取数据。

校验方法有:局部钩子,全局钩子,validators,和序列化类型和字段属性也是

字段属性

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

局部钩子

在序列化器类中创建局部钩子:validate_字段名,并且接收一个参数

# ser.py
class BooksSerializer(serializers.Serializer):
    title = serializers.CharField()
    publish = serializers.CharField()
    price = serializers.DecimalField(max_digits=5, decimal_places=2)

    # 局部钩子对price字段校验
    def validate_price(self, data):
        if float(data) > 20:
            # 校验成功就通过
            return data
        else:
            # 校验失败就抛异常
            raise ValidationError('价格太低')

全局钩子

全局钩子:validate( ), 接收一个参数,

同时对多个字段进行比较验证

# ser.py
class BooksSerializer(serializers.Serializer):
    title = serializers.CharField()
    publish = serializers.CharField()
    price = serializers.DecimalField(max_digits=5, decimal_places=2)

def validate(self, validate_data):
    title = validate_data.get('title')
    publish = validate_data.get('publish')
    if not title == publish:
        return validate_data
    else:
        raise ValidationError('书名和出版社不能一致')

validators

使用字段的validators=[func],来校验

# ser.py
# 校验函数
def check_price(data):
    if float(data) > 10:
        return data
    else:
        raise ValidationError('价格太低')

class BooksSerializer(serializers.Serializer):
    title = serializers.CharField()
    publish = serializers.CharField()
    price = serializers.CharField(validators=[check_price]) # 配置

四、序列化器操作数据

查询所有

# views.py
class BooksView(APIView):
    def get(self, request):
        # 响应信息
        response_msg = {'status': 200, 'message': '查询成功'}
        # 获取所有数据
        books = Books.objects.all()
        # 把数据谁传到序列化器中
        book_ser = BooksSerializer(instance=books, many=True) # 序列化多条需要加 many=True
        # book_ser.data————》序列化对象.data————》就是序列化后的字典
        # 将查询结果添加到响应信息内
        response_msg['data'] = book_ser.data
        return Response(response_msg)

# urls.py
path('books/', views.BooksView.as_view()),

查询单条

# views.py
class BookView(APIView):
    def get(self, request, pk):
        # 响应信息
        response_msg = {'status': 200, 'message': '查询成功'}
        # 获取要序列化的对象
        book = Books.objects.filter(pk=pk).first()
        # 要序列化谁就把谁传到序列化器中
        book_ser = BooksSerializer(instance=book)
        # book_ser.data————》序列化对象.data————》就是序列化后的字典
        # 将查询结果添加到响应信息内
        response_msg['data'] = book_ser.data
        return Response(response_msg)

# urls.py
re_path(r'^book/(?P<pk>\d+)/', views.BookView.as_view()),

新增数据

新增数据需要在序列化器中重写create( ) 方法:

注意没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,调用save()方法的时候,update()被调用。

# views.py
class BookView(APIView):
    def post(self, request):
        # 响应信息
        response_msg = {'status': 201, 'message': '增加成功'}
        # 修改才有instance,新增没有instance,只有data
        book_ser = BooksSerializer(data=request.data)

        # 校验字段
        if book_ser.is_valid():
            book_ser.save()  # 需要在序列化器中重写create()方法
            # 保存成功把原数据返回
            response_msg['data'] = book_ser.data
        else:
            response_msg['status'] = 202
            response_msg['message'] = '数据校验失败'
            response_msg['data'] = book_ser.error_messages
        return Response(response_msg)

# ser.py
class BooksSerializer(serializers.Serializer):
    title = serializers.CharField()
    publish = serializers.CharField()
    price = serializers.DecimalField(max_digits=5, decimal_places=2)

    # 重写create
    def create(self, validated_data):   # validated_data——>传入的新增数据
        instance = Books.objects.create(**validated_data)
        # instance——> 新增的字段对象,需要返回
        return instance

# urls.py
path('book/', views.BookView.as_view()),

修改数据

修改数据需要在序列化器中重写update( ) 方法:

# views.py
class BookView(APIView):
    def put(self, request, pk):
        # 响应信息
        response_msg = {'status': 200, 'message': '修改成功'}
        # 获取需要修改的字段对象
        book = Books.objects.filter(pk=pk).first()
        # 将字段对象和修改数据添加到序列化器中
        book_ser = BooksSerializer(instance=book, data=request.data)

        # 校验数据
        if book_ser.is_valid():
            book_ser.save()     # 需要在序列化器中重写update()方法
            response_msg['data'] = book_ser.data
        else:
            response_msg['status'] = 202
            response_msg['message'] = '数据校验失败'
            response_msg['data'] = book_ser.error_messages
        return Response(response_msg)

# urls.py
re_path('book/(?P<pk>\d+)', views.BookView.as_view()),

删除数据

# views.py
class BooksView(APIView):
    def delete(self, request, pk):
    # 响应信息
    response_msg = {'status': 200, 'message': '删除成功'}
    # 删除数据
    Books.objects.filter(pk=pk).delete()
    return Response(response_msg)

# urls.py
re_path('book/(?P<pk>\d+)', views.BooksView.as_view()),

五、模型类序列化器

DRF提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。

ModelSerializer与常规的Serializer相同,但是提供了:

  • 基于模型类自动生成一系列字段
  • 基于模型类自动为Serializer生成validators,比如unique_together
  • 包含默认的create( ) 和update( )。

实例:

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book        # 指明参照那个模型类
        fields = '__all__'  # 为模型类的那些字段生成

字段操作

1、可以使用fields来明确字段,__all__表示包含所以字段,具体那些字段->fields = ('title','price')

2、exclude表示排除那些字段,不能和fields一起写——>exclude = ('price',)

3、额外参数extra_kwargs,给字段添加额外的参数

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book        # 指明参照那个模型类
        fields = '__all__'  # 为模型类的那些字段生成

        # 类似于  title = serializers.CharField(read_only = True)
        extra_kwargs = {
            'title': {'read_only': True},
        }

六、源码分析many=True

当我们需要查询多条数据时就需要在实例化序列化器的时候传many=True

book_ser = BooksSerializer(instance=books, many=True) # 查询多条
book_one_ser = BooksSerializer(instance=book) # 查询单条

print(type(book_ser))
#<class 'rest_framework.serializers.ListSerializer'>

print(type(book_one_ser))
#<class 'app01.ser.BookModelSerializer'>

# 对象的生成-->先调用类的__new__方法,生成空对象,如果many=True,生成ListSerializer对象,反之生成Serializer对象

# 类的__new__方法控制对象的生成
def __new__(cls, *args, **kwargs):
    # 如果many=True,就会自动创建ListSerializer类
    if kwargs.pop('many', False):
        return cls.many_init(*args, **kwargs)
    return super().__new__(cls, *args, **kwargs)

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

(0)

相关推荐

  • DRF框架API版本管理实现方法解析

    API 不可能一成不变,无论是新增或者删除已有 API,都会对调用它的客户端产生影响.如果对 API 的增删没有管理,随着 API 的增增减减,调用它的客户端就会逐渐陷入迷茫,到底哪个 API 是可用的?为什么之前可用的 API 又不可用了,新增了哪些 API 可以使用?为了方便 API 的管理,我们引入版本功能. 给 API 打上版本号,在某个特定版本下,原来已有的 API 总是可用的.如果要对 API 做重大变更,可以发布一个新版本的 API,并及时提醒用户 API 已变更,敦促用户迁移到新

  • Django框架之DRF 基于mixins来封装的视图详解

    基础视图 示例环境搭建:新建一个Django项目,连接Mysql数据库,配置路由.视图函数.序列化单独创建py文件 # 配置路由 from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^PublishView/', views.PublishView.as_vi

  • python drf各类组件的用法和作用

    DRF组件的用法和作用 认证 自定义认证的类 """ from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from authapp.models import UserToken class MyOrderAuthentication(BaseAuthentication): 在这里实现认证

  • DRF使用simple JWT身份验证的实现

    前言 在Django的前后端分离项目中DRF(Django Restframe Work)框架无疑是首选,关于token验证一般使用的是JWT,但是JWT只支持到Django1.x的版本. 官方推荐Django2.x之后的版本使用simple JWT,官方文档. 登录返回token和refresh user 模型类: 我user模型类继承的是django.contrib.auth.models.AbstractUser,这样可以使用Django自带的认证. 如果继承该类,我们就必须在settin

  • Django DRF APIView源码运行流程详解

    首先写一个简单的drf接口 from rest_framework.views import APIView from rest_framework.response import Response # 基于drf写接口,cbv class DrfTest(APIView): def get(self, request,*args,**kwargs): print(type(request._request)) print(type(request)) print(request.POST) p

  • DRF跨域后端解决之django-cors-headers的使用

    在使用django-rest-framework开发项目的时候我们总是避免不了跨域的问题,因为现在大多数的项目都是前后端分离,前后端项目部署在不同的web服务器上,因为我们是后端程序员,因此我要通过后端的程序实现跨域.当然如果前端框架是Vue的话,则可以代理服务实现跨域,我也就知道一点点,如果有兴趣,大家可以自行搜索哦. DRF后端实现跨域我们使用一个第三方扩展--- djangocorsheaders 安装 pip install django-cors-headers 注册 INSTALLE

  • Django drf请求模块源码解析

    DRF 框架,全称为 Django Rest Framework,是 Django 内置模块的扩展,用于创建标准化 RESTful API:它利用 ORM 映射数据库,并自定义序列化数据进行返回,多用于前后端分离项目 项目地址: https://github.com/encode/django-rest-framework 请求模块:request对象 源码入口 APIView类中dispatch方法中的:request=self.iniialize_request(*args, **kwarg

  • django DRF图片路径问题的解决方法

    前言 其实就是Django RESTful Framework,RESTful一种API的命名风格,主要因为前后端分离开发出现,前后端分离: 用户访问静态文件的服务器,数据全部由ajax请求给到,RESTful风格:数据应该是名词,而动词由HTTP的请求方式来体现,RESTful风格的API给前端返回 结果对象,无论什么请求方式 本文主要介绍了关于django DRF图片路径问题,下面话不多说了,来一起看看详细的介绍吧 问题描述: 为什么DRF中有时候返回的json中图片是带域名的,有时候是不带

  • drf序列化器serializer的具体使用

    目录 一.序列化器-serializer 二.序列化器的使用 简单使用 高级使用 source **SerializerMethodField( ) ** 通用参数 三.反序列化数据校验 字段属性 局部钩子 全局钩子 validators 四.序列化器操作数据 查询所有 查询单条 新增数据 修改数据 删除数据 五.模型类序列化器 六.源码分析many=True 一.序列化器-serializer 序列化,序列化器会把模型对象转成字典,经过response以后变成JSON字符串 反序列化:把客户端

  • 解决RedisTemplate的key默认序列化器的问题

    redis的客户端换成了spring-boot-starter-data-redis,碰到了一个奇怪的问题, 在同一个方法中 1.先hset,再hget,正常获得数据. 在不同的方法中 先hset,再hget获取不到数据,通过redis的monitor监控发现了命令的问题: 实际我的key为JK_HASH:csrk,hashkey为user,但是根据上图所示,实际执行的命令多了好多其他字符,这是什么原因呢? 在服务器端先确认发现实际有这个Hash,通过hset可以得到正确的数据,所以第一次执行h

  • 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视图扩展类知识点详解

    扩展类必须配合GenericAPIView使用扩展类内部的方法,在调用序列化器时,都是使用get_serializer 需要自定义get.post等请求方法,内部实现调用扩展类对应方法即可 . 一.mixins的视图子类 作用: 提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量 . 这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提

  • django Serializer序列化使用方法详解

    Serializer序列化器 定义Serializer 1. 定义方法 Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer. 例如,我们已有了一个数据库模型类BookInfo class BookInfo(models.Model): btitle = models.CharField(max_length=20, verbose_name='名称') bpub_date = mode

  • Django模型序列化返回自然主键值示例代码

    场景 在设计表结构时,难免需要建立一些外键关联.例如这样两个模型: from django.db import models class Person(models.Model): username = models.CharField(max_length=100) birthdate = models.DateField() class Book(models.Model): name = models.CharField(max_length=100) author = models.Fo

  • Django框架中序列化和反序列化的例子

    1.序列化 DRF的核心 就是 前后端分离的核心 前后端分离开发的核心: 将模型转换为json 称之为 序列化 将json转换为模型 称之为 反序列化 1.序列化器的字段 Serializer 序列化器 为了得到模型里的字段,序列化器中的字段应与模型类中的字段名一致 ''' serializers.py ''' class BookInfoSerializer(serializers.Serializer): # read_only=True 只能读 不能修改 id = serializers.

  • Django DRF路由与扩展功能的实现

    一. 视图集与路由的使用 使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中: list() 提供一组数据 retrieve() 提供单个数据 create() 创建数据 update() 保存数据 destory() 删除数据 ViewSet视图集类不再实现get().post()等方法,而是实现动作 action 如 list() .create() 等. 视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上. 1. 常用的视图集父类 1.Vi

  • django restframework序列化字段校验规则

    目录 一.怎么校验创建的项目名是否是唯一的,当项目名name字段不唯一,怎么设置提示信息? 二.项目名称中必须得包含“项目”2字 三.单个字段进行校验:项目名称不能多于10个字 四.多字段进行校验: 五.to_internal_value方法,是所有字段开始进行校验时的入口方法(最先调用的方法) 六.to_representation方法,是序列化输出的入口方法 一.怎么校验创建的项目名是否是唯一的,当项目名name字段不唯一,怎么设置提示信息? class ProjectsSerializer

随机推荐