Django框架之DRF序列化与反序列化

2023-10-31

概念:
序列化:将Python对象转换为json字符串,反之json字符串反序列化为对象
使用drf序列化组件的步骤如下
1.在你的app中新建一个py文件,新建一个序列化的类
2.在类中写要序列化的字段
在视图中使用序列化的类
1.实例化出一个序列化的对象,在产生对象的时候,传入序列化的对象(queryset对象)
2.对象.data
3.return Reponse(对象.data)
使用实例:
新建Django项目:settings.py文件注册rest_framework,使用MySQL数据库创建数据:

settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'drf_ser01',		#数据库的名字
        'HOST': '127.0.0.1', #数据库的ip
        'PORT': 3306,  #数据库的端口
        'USER': 'root', #数据库的用户名
        'PASSWORD': '123'
    }
}
# __init__.py
import pymysql
pymysql.install_as_MySQLdb()

from django.db import models

# Create your models here.


class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(decimal_places=1, max_digits=6)
    publish = models.ForeignKey(to='Publish')
    author = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book', 'author'))


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64, null=True)


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()


class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')

app01新建MySer.py

#先创建一个BookSer序列化类
from rest_framework import serializers
#第一种序列化方法
class BookSer(serializers.Serializer):
	id = serializers.CharField()
 	title = serializers.CharField()
    publish = serializers.CharField()
    author = serializers.CharField()
  #第二种序列化的类
  class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
     def validate_name(self,values):
        if values is None:
            raise ValidationError("名字不能为空")
        else:
            return values

app01视图函数views.py中:

from django.shortcuts import render,HttpResponse,redirect
from app01.MySer import BookSer
from rest_framework.response import Response
from rest_framework.views import APIView
from app01 import models

# Create your views here.

class Book(APIView):
    response = {'code': 100, 'msg': '查询成功'}
    def get(self, request):
        books = models.Book.objects.all()
        #注instance用于接受序列化的对象,many表示是queryset对象
        books_ser = BookSer(instance=books, many=True)
        return Response(books_ser.data)
   

路由配置:


from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^books/', views.Books.as_view()),
]

使用Postman发送get请求,获取到数据库中所有图书信息:
在这里插入图片描述
可以看出一对多和多对多的外键字段显示的是对象名字,下面进一步使用序列化,让信息显示更完善

-source:可以指定字段(name   publish.name),可以指定方法

-SerializerMethodField搭配方法使用(get_字段名字)                
publish_detail=serializers.SerializerMethodField(read_only=True)
def get_publish_detail(self,obj):
    return {'name':obj.publish.name,'city':obj.publish.city}

更新版本BookSer

from rest_framework import serializers


class BookSer(serializers.Serializer):
    id = serializers.CharField()
    title = serializers.CharField()
    #返回出版社的时候会返回出版社的名字
    publish = serializers.CharField(source='publish.name')
    author = serializers.SerializerMethodField()
    def get_author(self, obj):
        authors = []
        for author_obj in obj.author.all():
            authors.append({'name': author_obj.name, 'age': author_obj.age})
        return authors

在这里插入图片描述
注:

  • read_only:反序列化时,不传
  • write_only:序列化时,不显示
    序列化的另一种写法,上方有提过:
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields=('id','name')
        #要排除的字段
         exclude=('name')
          #深度控制
          depth=1
    def validate_name(self,values):
        if values is None:
            raise ValidationError("名字不能为空")
        else:
            return values

在这里插入图片描述
刚才看到__all__,序列化所有字段,查询到的数据里面publish和author都是对应id值,如果需要获取到对应publish和author的关联信息,可以在BookSer内,Meta外重新写字段,方式同serializers

class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
      	fields = "__all__"
    def validate_name(self,values):
        if values is None:
            raise ValidationError("名字不能为空")
        else:
            return values

在这里插入图片描述
如果只想取其中几个字段,可以进行指定:
改进:

class AuthorSer(serializers.Serializer):
    id = serializers.CharField()
    name = serializers.CharField()
    age = serializers.CharField()

# 序列化方式二改进:
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        # fields = ['id', 'title']
        fields = ('__all__')
    publish = serializers.CharField(source='publish.name')
    author = serializers.SerializerMethodField()
    def get_author(self, obj):
        ret = AuthorSer(obj.author.all(), many=True)        
        return ret.data

通过post请求新增数据:
对数据进行新增使用反序列化实现,这里反序列化有2种情况进行新增:
使用继承了Serializers序列化类的对象,反序列化(需重写create方法)

from django.db import models

# Create your models here.

class User(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    choices = (('1', 'Super_Admin'), ('2', 'General_Admin'), ('3', 'General_User') )
    user_type = models.CharField(max_length=6, choices=choices, default='3')

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(decimal_places=1, max_digits=6)
    publish = models.ForeignKey(to='Publish', null=True)
    author = models.ManyToManyField(to='Author')


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64, null=True)


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
class Book(APIView):
    def post(self, request):
        response = {'code': 100, 'msg': '新增成功'}
        # 使用继承了Serializers序列化类的对象,反序列化
        book = BookSer(data=request.data)
        if book.is_valid():
            # 清洗通过的数据,需要在MySer.py中重写create
            book.create(book.validated_data)
        return Response(response)
class BookSer(serializers.Serializer):
    # read_only 反序列化的时候,该字段不传
    # 这里id可以不传自增,publish、author不传,当然需要在models里面把不传字段设置为null=True
    # author多对多字段不能设置null=True
    id = serializers.CharField(read_only=True) 
    title = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField(source='publish.id', read_only=True)
    author = serializers.SerializerMethodField(read_only=True)
    def get_author(self, obj):
        ret = AuthorSer(obj.author.all(), many=True)
        return ret.data
    # 重写create方法,才能在使用Serializer发序列化方法进行新增数据
    def create(self, validated_data):
        res = models.Book.objects.create(**validated_data)
        return res

使用继承了ModelSerializers序列化类的对象,反序列化

from django.db import models

# Create your models here.

class User(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    choices = (('1', 'Super_Admin'), ('2', 'General_Admin'), ('3', 'General_User') )
    user_type = models.CharField(max_length=6, choices=choices, default='3')


class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(decimal_places=1, max_digits=6)
    publish = models.ForeignKey(to='Publish', null=True)
    author = models.ManyToManyField(to='Author')


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=64, null=True)


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
class Book(APIView):

    def post(self, request):
        response = {'code': 100, 'msg': '新增成功'}

        # 使用继承了ModelSerializers序列化类的对象,反序列化
        book_ser = BookSer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
        else:
            response['error'] = book_ser.errors['name'][0]
        return Response(response)

使用ModelSerializer反序列化save数据后,多对多关联的那张表也会自动关联产生新的数据。
局部校验和全局校验

# MySer.py

from rest_framework.exceptions import ValidationError
class BookSer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"

    def validate_title(self, value):
        if value.startswith('sb'):
            raise ValidationError('不能以sb开头')
        return value

    def validate(self, attrs):
        title = attrs.get('title')
        price = attrs.get('price')
        if title.startswith('禁书') or int(price) <= 15:
            raise ValidationError('书名或价格不正常')
        return attrs

总结:

-反序列化的校验
-validate_字段名(self,value):
-如果校验失败,抛出ValidationError(抛出的异常信息需要去bookser.errors中取)
-如果校验通过直接return value
-validate(self,attrs)
-attrs所有校验通过的数据,是个字典
-如果校验失败,抛出ValidationError
-如果校验通过直接return attrs

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Django框架之DRF序列化与反序列化 的相关文章

随机推荐

  • mysql如何将表导出到excel

    一 显示当前使用或者指定的database中的每个表的信息 信息包括表类型和表的最新更新时间 show table status 二 mysql如何将表结构导出到excel SELECT TABLE NAME 表名 COLUMN NAME
  • 计算机视觉与深度学习-图像分割-视觉识别任务03-实例分割-【北邮鲁鹏】

    目录 参考 定义 Mark R CNN 结构 思路 Mask R CNN训练阶段使用的Mask样例 Mask R CNN实例分割结果 Mask R CNN检测姿态 参考 论文题目 Mask R CNN 论文链接 论文下载 论文代码 Face
  • 四、在原理图中添加每个元件的封装

    画完每个元件的封装后 回到原理图界面 双击每个原理图元件 在编辑中添加封装 全部添加好右键点击原理图 选择validate pcb 那个 编译原理图文件 会自动检查错误 检查出来可以导出一个错误文档 然后根据文档修正即可 这个编译是将元件的
  • android点击后图片变大,Android实现点击缩略图放大效果

    import android animation Animator import android animation AnimatorListenerAdapter import android animation AnimatorSet
  • 【javascript】获取键盘输入

    获取上下左右键 在JavaScript中 如果我们想要获取键盘中的键对应的键码 可以使用event对象的keyCode属性
  • java连接kafka api_Kafka-JavaAPI(Producer And Consumer)

    Kafka JAVA API Producer和Consumer Kafka 版本2 11 0 9 0 0 producer package com yzy spark kafka import kafka javaapi producer
  • 2008年北大信科研究生复试 机考真题(一)--大数据十进制转换

    描述 将一个长度最多为30位数字的十进制非负整数转换为二进制数输出 输入 多组数据 每行为一个长度不超过30位的十进制非负整数 注意是10进制数字的个数可能有30个 而非30bits的整数 输出 每行输出对应的二进制数 样例输入 0 1 3
  • LogBack的使用

    需要JAR包 1 slf4j api 1 6 1 jar 2 logback access 0 9 29 jar 3 logback classic 0 9 29 jar 4 logback core 0 9 29 jar 加载顺序 1 l
  • Promise详解

    1 基本概念 Promise是JS异步编程中的重要概念 异步抽象处理对象 是目前比较流行Javascript异步编程解决方案之一 2 Promise的三种状态 pending 对象初始化状态 fulfilled 当调用resolve 成功
  • 计算机管理找不到防火墙,win10系统防火墙服务找不到的具体方案

    win10系统使用久了 好多网友反馈说win10系统防火墙服务找不到的问题 非常不方便 有什么办法可以永久解决win10系统防火墙服务找不到的问题 面对win10系统防火墙服务找不到的图文步骤非常简单 只需要从电脑桌面找到计算机 然后鼠标指
  • Effective C++ 学习笔记 条款06 若不想使用编译器自动生成的函数,就应该明确拒绝

    如想阻止拷贝 但编译器为类声明了拷贝构造函数和拷贝赋值运算符 这样就不能达到目的了 你可以通过将拷贝构造函数和拷贝赋值运算符声明为private的来阻止拷贝 但类的成员函数和友元还是可以调用 此时将它们声明但不定义就行了 这样调用它的函数会
  • 通过href 从http跳转https失效问题 前端解决

    目前 浏览器定位的功能大多数浏览器为了安全需要https协议才可使用 这就需要站点支持https协议 尝试通过a标签跳转至a目录下的index html 发现href中目标地址是https xxx com a 浏览器跳转到https xxx
  • 攻防世界:WEB新手练习区

    题目 https adworld xctf org cn challenges problem set index id 25 rwNmOdr 1678625790128 view source 题目描述 X老师让小宁同学查看一个网页的源代
  • 开源阅读书源_安卓神器

    Hi 新朋友 记得点蓝字关注我们哟 阅读 大家好 我是小昊 今天在论坛看到有人提到这个软件 我才记起来要老早就应该给大家推荐这个软件的 首先这个软件是需要自己添加源的 不加是用不了的哟 如
  • Docker安装以及常用命令

    提示 以下内容均为学习过程中的个人笔记 有用自取 无用勿喷 如有错误欢迎指正 一 什么是docker Docker 是采用Linux Container 基于Golang语言 采用apache2 0开源协议存储于GitHub开源的容器管理引
  • 【网络是怎样连接的】—— TCP/IP 传输数据

    协议栈的工作原理 1 协议栈的内部结构 操作系统中的网络控制软件 协议栈 的内部如图所示 分为几个部分 分别承担不同的功能 这张图中的上下关系具有一定的规则 上面的部分会向下面的部分委派工作 下面的部分接受委派的工作并实际执行 图中最上面的
  • 解决APK签名问题the apk for your currently selected variant(app-release-unsigned.apk)is not signed.

    转载地址 https www cnblogs com galibujianbusana p 7694087 html
  • C语言面试题汇编

    1 局部变量能否和全局变量重名 答 能 局部会屏蔽全局 要用全局变量 需要使用 局部变量可以与全局变量同名 在函数内引用这个变量时 会用到同名的局部变量 而不会用到全局变量 对于有些编译器而言 在同一个函数内可以定义多个同名的局部变量 比如
  • spdlog用法

    转自 spdlog学习笔记 说明 所有内容翻译自spdlog的wiki 受英语水平所限 有所错误或失真在所难免 如果您有更好的建议 请在博文下留言 线程安全 spdlog 命名空间下的是线程安全的 当loggers在不同的线程同时执行时 下
  • Django框架之DRF序列化与反序列化

    概念 序列化 将Python对象转换为json字符串 反之json字符串反序列化为对象 使用drf序列化组件的步骤如下 1 在你的app中新建一个py文件 新建一个序列化的类 2 在类中写要序列化的字段 在视图中使用序列化的类 1 实例化出