Backend - DRF 序列化(django-rest-framework)

news2024/11/25 7:14:55

目录

一、restful 、django-rest-framework 、swagger 三者的关系

(一)restful API(REST API)

1. rest

2. restful

3. api

4. restfulAPI

(二)django-rest-framework(简称DRF)

(三)swagger

二、DRF 基础配置

(一)安装依赖

(二)配置环境

三、自定义序列化器(定义序列化类,serializers)

(一)Django 序列化 & DRF 序列化器

1. Django 序列化

(1)序列化

(2)反序列化

2. DRF 序列化器

(二)序列化类

(三)常用字段

1. 序列化器的常用字段

2. 自定义字段类型

3. 字段的many参数

4. 字段的多关系子序列化 

(1)source参数的使用

① 重命名字段

② 跨表

③ 执行方法

(2)SerializerMethodField的使用

5. fields的必要性

6. exclude

7. validate_字段名

(四) 创建序列化器(定义序列化类)

1. 一般写法

2. 公共字段

四、使用序列化器(实例化)

(一)构造序列化对象

1. data

2. instance

(二)实例化后的类属性

1. data 属性

2. 实际应用

(1)单个数据模型

(2)多个数据模型

(三)实例化后的类方法

1. is_valid( ) 方法

(1)作用

(2)参数raise_exception

(3)配合validate_字段

2. save() 方法

3. 两者举例

(1)简单举例

(2)完整应用

(四)运行查看

1. 设置路由(urls)

2. 运行情况

五、问题解决

1. ValidationError({'non_field_errors': [ErrorDetail(string='Expected a list of items but got type "dict".', code='not_a_list')]})

2. "The field 'XXX' was declared on serializer SerializerRecipeBodySave, but has not been included in the 'fields' option."


一、restful 、django-rest-framework 、swagger 三者的关系

(一)restful API(REST API)

1. rest

        架构的设计风格,即架构规范(该篇文章主要针对接口的请求方式)。

2. restful

        符合rest原则的开发理念(设计标准)。

3. api

        通讯接口。

4. restfulAPI

        使用REST风格理念的接口(每一种请求API,对应后端的一种数据库操作)。

(二)django-rest-framework(简称DRF)

        是针对Django,生成restfulAPI的框架(序列化)。

        即,给Django提供了跨平台跨语言的Web API框架。

        需安装依赖 djangorestframework,settings.py的INSTALLED_APPS引入rest_framework。

(三)swagger

        针对django-rest-framework(DRF),遵循rest风格理念(restful),生成接口开发文档的工具(UI 界面,可测试、也方便前后端对接)。

        需安装依赖 drf-yasg,settings配置INSTALLED_APPS引入drf_yasg。

swagger的应用,可参考另一篇文章:Backend - Django Swagger-CSDN博客

二、DRF 基础配置

(一)安装依赖

pip install djangorestframework==3.14.0

(二)配置环境

    # settings.py文件中
    INSTALLED_APPS = [
        ...
        'rest_framework',
        ...
    ]

三、自定义序列化器(定义序列化类,serializers)

主要针对Serializers.py 和Models.py。

(一)Django 序列化 & DRF 序列化器

1. Django 序列化

针对DRF的序列化器的应用来讲:

(1)序列化

        序列器将orm模型或queryset物件转换成字典,再由response把字典转换成json的过程。

        即,后端传数据给前端时,将“查询集QuerySet格式”,最终序列化转为“json格式”。

(2)反序列化

        序列化器将request获取的json数据转化为python对象。

        即,前端将数据传给后端时,将json数据,最终反序列化为python对象。

2. DRF 序列化器

        虽然,Django有自带的序列化类(serializers类),但DRF提供的序列化器更实用。

(二)序列化类

        序列化器的序列化类有3种:

        Serializer、ListSerializer、ModelSerializer(最常用的)

(三)常用字段

1. 序列化器的常用字段

        CharField,IntegerField,DateField、BooleanField

2. 自定义字段类型

# 例如自定义Combobox
# 自定义复选框字段类型
class Combobox(serializers.Serializer):
	 bookname = serializers.CharField()
	 bookid = serializers.IntegerField()
# 使用复选框字段
class SerializerAuthor(serializers.Serializer):
	 age = serializers.BooleanField()
	 name = serializers.CharField()
	 books = Combobox(many=False)

3. 字段的many参数

        序列化单个对象,默认参数many=False

        序列化多个对象,指定参数many=True

4. 字段的多关系子序列化 

(1)source参数的使用
① 重命名字段

        自定义返回给前端的字段名。

② 跨表

        获取外键表的字段。

③ 执行方法

        执行model模型类内的自定义方法。

# models.py
class BookType(models.Model):
	bid = models.AutoField(primary_key=True)
	name = models.CharField(max_length=32)
    color = models.CharField(max_length=32)
	fontsize = models.CharField(max_length=32)
	fontcolor = models.CharField(max_length=32)

class PublishPlace(models.Model):
	nid = models.AutoField(primary_key=True)
	name = models.CharField(max_length=32)
	status =  models.BooleanField(default=True, db_index=True)
	city = models.CharField(max_length=32)
	email = models.CharField(max_length=32)

class Author(models.Model):
	aid = models.AutoField(primary_key=True)
	name = models.CharField(max_length=32)
    age = models.IntegerField(default=10)
	sex = models.CharField(max_length=32)
	birthday = models.DateField()

class Book(models.Model):
	bid = models.AutoField(primary_key=True)
	name = models.CharField(max_length=32)
	price = models.DecimalField(max_digits=5, decimal_places=2)
    booktype =  models.ForeignKey(to='BookType', to_field='bid', on_delete=models.CASCADE)
	publish = models.ForeignKey(to='PublishPlace', to_field='pid', on_delete=models.CASCADE)
	authors = models.ManyToManyField(to='Author')

	def __str__(self):
		return self.name

	# 取出该书的出版社
	def getpublishdata(self):
		return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email}
    # 取出该书的所有作者
	def all_author(self):
		return [{'id': author.aid, 'name': author.name, 'age': author.age} for author in self.authors.all()]
# serializers.py 
from rest_framework import serializers
from myAPP import model # 引入model.py
class AuthorSerializer(serializers.ModelSerializer):
	class Meta:
		model = Author
		fields = "__all__"

class SerializerBook(serializers.ModelSerializer):
	authors = AuthorSerializer(many=True)
	book_price = serializers.CharField(source='price') # price是数据库字段,book_price 是自命名的。
	book_type = serializers.CharField(source='booktype.name') # booktype是关联“书籍类型表”的外键字段。name是“书籍类型表”的字段。
	publish2 = serializers.DictField(source="getpublishdata") # 字典形式(执行模型类的方法)
	class Meta:
			model = model.Book
			fields = [ 'name', 'publish', 'authors', 'Publish2', 'book_price','book_type'] 
            # fields是设置最后返回的数据有哪些。book_price和book_type、Publish2 是上方自定义的字段名。 name、Publish、authors是数据库原本的字段名。
(2)SerializerMethodField的使用

        需要搭配 get_XXX( ) 方法。

        可自定义返回给前端的字段值格式。

        一般用于跨表查询。

# serializers.py
class SerializerBook(serializers.ModelSerializer):
	publish = serializers.SerializerMethodField() #设置序列化,才能用下面的get__XXX()方法。
	booktype = serializers.SerializerMethodField() 
	class Meta:
			model = model.Book
			fields = ['publish']  
	def get_publish(self, obj): # 自定义返回的数据格式
			return {'label': obj.city, 'value': obj.email} # city和email都是publish字段关联到的外表publishplace表的字段

	def get_booktype(self, obj):
			booktypes=obj.booktypes.all()  # 全部书籍样式
			b_list=list()
			for booktype in booktypes:
				b_list.append({'name':booktype.color,'age':booktype.fontsize})
			return b_list

5. fields的必要性

        自定义的字段、前端展示的字段,都需要在fields中填写。

6. exclude

        排除不需要显示的字段。

        注意:fields和exclude不能共存。

7. validate_字段名

        写在序列化器中(serializers.py中)。

        需要搭配实例化后的is_valid()方法(views.py中)。实例化序列化器在后面的模块中会讲。

class BookInfoSerializer(serializers.Serializer):
	price = serializers.BooleanField()
	name = serializers.CharField()
	class Meta:
		model = model.Book
		fields = [ 'name', 'price','booktype']

# ① 验证单个字段
	def validate_booktype(self, value):
		if '教育' not in value:
			raise serializers.ValidationError("该书籍不属于教育")
		return value
# ② 验证多个字段
	def validate(self, vals):
		price = vals['price'] 
		booktype = vals['booktype']
		if  booktype =='教育' and price > 100  
			raise serializers.ValidationError("该教育书籍价格大于100")
		return value

(四) 创建序列化器(定义序列化类)

上述自定义序列化器中的一些相关实例,也有讲创建序列化器。

1. 一般写法

# 在myBook项目下新建book_serializer.py文档
from book_models import Book, Author
from rest_framework import serializers
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book  # model名
        fields = '__all__'

2. 公共字段

# 在myBook项目下新建book_serializer.py文档
from book_models import Book, Author
from rest_framework import serializers

# 不同的序列化,有共同字段
class BaseData(serializers.ModelSerializer):
	decription = serializers.CharField()

class BookSerializer(BaseData):
	 class Meta:
		 model = Book  # model名
		 fields = ['name', 'card', 'place', 'author', 'decription']

class AuthorSerializer(BaseData):
	 class Meta:
		 model = Author  # model名
		 fields = ['name', 'sex', 'age', 'place', 'decription']  

四、使用序列化器(实例化)

主要针对views.py。

(一)构造序列化对象

Serializer(instance=None, data=empty, **kwarg)  # 构造方法,初始化

其中,可传入 instance, data 等参数。

1. data

        是需要验证的资料,预设为empty。

2. instance

        格式:是针对某条queryset数据,预设为None。

        作用:

               实例化serializer(创建序列化对象)时,根据是否传入instance参数,判断执行update还是create。

                即,若传入的instance有值时,则instance.save调用update方法;

                反之,若传入的instance为None(或没有传instance)时,则instance.save调用create方法。

(二)实例化后的类属性

1. data 属性

        获取序列化后的数据。

2. 实际应用

(1)单个数据模型

# 在myBook项目下新建views_book.py文档
from rest_framework.generics import GenericAPIView
from django.http import JsonResponse
from django.db import transaction
from book_models import Book
from book_serializers import BookSerializer 

class BookView(GenericAPIView):
	def get(self, request, *args, **krgs):
		books_qst = Book.objects.get(id=1)  # 获取单笔数据
		book_seri = BookSerializer(books_qst, many=True)  # 数据转换,即数据序列化
		res =  book_seri.data  # 获取数据  {'id': 1, 'bookname': '数据结构', 'author': '萝卜干'}
		return JsonResponse(res)
(2)多个数据模型
# 在myBook项目下新建views_book.py文档
from rest_framework.generics import GenericAPIView
from django.http import JsonResponse
from django.db import transaction
from book_models import Book
from book_serializers import BookSerializer 

class BookView(GenericAPIView):
	def get(self, request, *args, **krgs):
		books_qst = Book.objects.all()  # 查询数据库,获取多笔数据
		book_seri = BookSerializer(books_qst, many=True)  # many=True,表示序列化多条数据
		res =  book_seri.data  # 获取数据 [('id', 1), ('bookname', '数据结构'),  ('author', '萝卜干')]
		return JsonResponse(res, safe=False) # 结果是列表,则需声明safe=False

(三)实例化后的类方法

1. is_valid( ) 方法

(1)作用

        验证newdata是否符合数据库数据规范。

(2)参数raise_exception

        raise_exception=True # 若验证时出现异常,会接收到此异常,向前端返回HTTP 400 响应。

(3)配合validate_字段

        在上述自定义序列化器的模块中,有讲解如何使用。

2. save() 方法

        保存当前数据。

3. 两者举例

(1)简单举例
bookins = models.Book.objects.first()
myserializer = BookSerializer(instance=bookins, data=newdata, partial=True)
myserializer.is_valid(raise_exception=True)
myserializer.save()
(2)完整应用
# 在myBook项目下新建views_book.py文档
from rest_framework.generics import GenericAPIView
from django.http import JsonResponse
from django.db import transaction
from book_models import Book
from book_serializers import BookSerializer 

class BookView(GenericAPIView):
	def post(self, request, *args, **krgs):
		book_data = request.data
		try:
			serializer =BookSerializer(data=book_data)  # 更改数据库
			serializer.is_valid(raise_exception=True)  # 检查是否合格
			with transaction.atomic(): 
				serializer.save()
			res = serializer.data # 获取序列化后的数据
		except Exception as e:
			res = {'error': str(e)}
		return JsonResponse(res)

(四)运行查看

1. 设置路由(urls)

        展示序列化数据的整体流程,涉及models、serializers、views、urls 模块。

# 在myPro项目下新建urls.py文档
from django.urls import path, re_path  # url规则
from myBook import views_book as book_view

urlpatterns = [
    ...
     path('book/', book_view.BookView.as_view()),
] 

2. 运行情况

        浏览器输入链接,回车。

        链接:http://127.0.0.1:8080/myApp/book

        展示界面如下:

五、问题解决

1. ValidationError({'non_field_errors': [ErrorDetail(string='Expected a list of items but got type "dict".', code='not_a_list')]})

原因:在使用序列化时,many设置了为True。表示存入多笔,但实际若只存单笔,则会报错。

解决:many设置为False,或删除该属性。

2. "The field 'XXX' was declared on serializer SerializerRecipeBodySave, but has not been included in the 'fields' option."

原因:字段 XXX 已在序列化程序上声明,但尚未包含在fields“字段”选项中。

解决:在 fields = (  ) 中加上该字段。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1600503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分类算法——模型选择与调优(三)

交叉验证 交叉验证:将拿到的训练数据,分为训练和验证集。以下图为例:将数据分成4份,其中 一份作为验证集。然后经过4次(组)的测试,每次都更换不同的验证集。即得到4组模型的 结果,取…

进程间通信--共享内存

1.共享内存介绍 共享内存为多个进程之间共享和传递数据提供了一种有效的方式。共享内存是先在物 理内存上申请一块空间,多个进程可以将其映射到自己的虚拟地址空间中。 所有进 程都可以访问共享内存中的地址,就好像它们是由 malloc 分配的一样。如果某个进 程向共享内存写入了…

随着深度学习的兴起,浅层机器学习没有用武之地了吗?

深度学习的兴起确实在许多领域取得了显著的成功,尤其是那些涉及大量数据和复杂模式的识别任务,如图像识别、语音识别和自然语言处理等。然而,这并不意味着浅层机器学习(如支持向量机、决策树、朴素贝叶斯等)已经失去了…

Achronix FPGA增加对Bluespec提供的基于Linux的RISC-V软处理器的支持,以实现可扩展数据处理

Bluespec支持加速器功能的RISC-V处理器将Achronix的FPGA转化为可编程SoC 2024年4月——高性能FPGA芯片和嵌入式FPGA(eFPGA)硅知识产权(IP)领域的领先企业Achronix半导体公司,以及RISC-V工具和IP领域的行业领导者Blues…

Matlab分段微分方程组拟合【案例源码+视频教程】

专栏导读 作者简介:工学博士,高级工程师,专注于工业软件算法研究本文已收录于专栏:《复杂函数拟合案例分享》本专栏旨在提供 1.以案例的形式讲解各类复杂函数拟合的程序实现方法,并提供所有案例完整源码;2.…

OpenHarmony开发实例:【新闻客户端】

介绍 本篇Codelab我们将教会大家如何构建一个简易的OpenHarmony新闻客户端(JS版本)。应用包含两级页面,分别是主页面和详情页面,两个页面都展示了丰富的UI组件,其中详情页的实现逻辑中还展示了如何通过调用相应接口&a…

【Java NIO】那NIO为什么速度快?

Java IO在工作中其实不常用到,更别提NIO了。但NIO却是高效操作I/O流的必备技能,如顶级开源项目Kafka、Netty、RocketMQ等都采用了NIO技术,NIO也是大多数面试官必考的体系知识。虽然骨头有点难啃,但还是要慢慢消耗知识、学以致用哈…

百度智能云万源全新一代智能计算操作系统发布:引领AI新纪元,开启智能未来

随着科技的迅猛发展,人工智能(AI)逐渐渗透到我们生活的每个角落,为人类社会带来前所未有的变革。在这场科技革命的浪潮中,百度作为中国AI领域的领军企业,始终站在技术创新的前沿,不断引领行业发…

【架构-14】数据库性能优化方式

数据库出现性能瓶颈对外的表现为: 大量请求阻塞SQL操作变慢存储出现问题 为解决上述出现的问题,因此推出了一系列的数据库性能优化方式。 数据库性能优化是提高数据库系统性能和响应时间的关键任务。以下是一些常见的 数据库性能优化方式: …

在Qt中如何简单设计一个文件和图像浏览器

文本浏览器 设计一个文本浏览器程序,可以打开、显示 txt、html等文件。 1.在Qt Designer中设计一个菜单其中包含打开和退出选项: 2. 在 QMainWindow 构造函数中把 textBrower 设为主窗口的中心部件,这样整个窗口就成了包含 textBrower 的单文…

免费的 ChatGPT、GPTs、AI绘画(国内版)

🔥博客主页:白云如幻❤️感谢大家点赞👍收藏⭐评论✍️ ChatGPT3.5、GPT4.0、GPTs、AI绘画相信对大家应该不感到陌生吧?简单来说,GPT-4技术比之前的GPT-3.5相对来说更加智能,会根据用户的要求生成多种内容甚…

Elasticsearch的使用教程

Elasticsearch简介 Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。作为 Elastic Stack 的核心,Elasticsearch 会集中存储您的数据,让您飞快完成搜索,微调相关性,进行…

【读论文】【泛读】三篇生成式自动驾驶场景生成: Bevstreet, DisCoScene, BerfScene

文章目录 1. Street-View Image Generation from a Bird’s-Eye View Layout1.1 Problem introduction1.2 Why1.3 How1.4 My takeaway 2. DisCoScene: Spatially Disentangled Generative Radiance Fields for Controllable 3D-aware Scene Synthesis2.1 What2.2 Why2.3 How2.4…

hadoop编程之工资序列化排序

数据集展示 7369SMITHCLERK79021980/12/17800207499ALLENSALESMAN76981981/2/201600300307521WARDSALESMAN76981981/2/221250500307566JONESMANAGER78391981/4/22975207654MARTINSALESMAN76981981/9/2812501400307698BLAKEMANAGER78391981/5/12850307782CLARKMANAGER78391981/…

【Image captioning】论文阅读九—Self-Distillation for Few-Shot Image Captioning_2022

摘要 大规模图像字幕数据集的开发成本高昂,而大量未配对的图像和文本语料库可能有助于减少手动注释的工作。在本文中,我们研究了只需要少量带注释的图像标题对的少样本图像标题问题。我们提出了一种基于集成的自蒸馏方法,允许使用不成对的图像和字幕来训练图像字幕模型。该…

Flask Web 应用与 MongoDB 集成:用户登录和退出

在本文中,我们将探讨如何使用 Flask Web 框架和 MongoDB 数据库构建一个简单的 Web 应用。我们将使用 Flask-PyMongo 扩展来实现 MongoDB 集成,并使用 Flask-Login 扩展来处理用户认证。 1. 安装所需库 首先,我们需要安装 Flask、Flask-PyM…

如何利用纯前端技术,实现一个网页版视频编辑器?

纯网页版视频编辑器 一、前言二、功能实现三、所需技术四、部分功能实现4.1 素材预设4.2 多轨道剪辑 一、前言 介绍:本篇文章打算利用纯前端的技术,来实现一个网页版的视频编辑器。为什么突然想做一个这么项目来呢,主要是最近一直在利用手机…

初识数据库与数据库管理系统

实体的概念与数据库 实体(对象): 客观存在的事物都是实体实体数据的存储要求: 必须按照一定的分类和规律存储数据库: 专门用于存储这些实体的信息的数据集合数据库的特点: 海量存储数据/数据检索非常方便保持数据信息的一致/完整/并实现数据…

C# .NET 中的反应式系统

概述:反应式系统已成为构建健壮、可扩展和响应迅速的应用程序的强大范式。这些系统被设计为更具弹性、弹性和消息驱动性,确保它们在各种条件下保持响应,包括高负载、网络延迟和故障。在本文中,我们将探讨 .NET 生态系统中反应式系…

Day 15 Linux网络管理

IP解析 IP地址组成:IP地址由4部分数字组成,每部分数字对应于8位二进制数字,各部分之间用小数点分开,这是点分2进制。如果换算为10进制我们称为点分10进制。 每个ip地址由两部分组成网络地址(NetID)和主机地址(HostID).网络地址表…