前言

上一篇文章我们讲述了序列化,这篇就带大家一起来实现以下序列化

Serializer

我们使用序列化类Serializer,我们来看下源码结构,这里推荐使用pycharm左边导航栏的Structure,可以清晰的看到一个文件的结构,如下图



我们会发现Serializer继承自BaseSerializerSerializerMetaclass,但是Serializer类中又没有create方法和update方法,所以我们使用的时候必须自己手动定义这2个方法

准备工作

1.新建一个项目drf_demo,在项目中新建一个appdrf_app,在app中新建一个文件urls.py,项目结构如下

2.在models.py文件中写入如下代码

class Student(models.Model):

    SEX_CHOICES = (
(1,'男'),
(2, '女')
) name = models.CharField(max_length=20, verbose_name='姓名')
age = models.IntegerField(null=True, blank=True, verbose_name='年龄')
sex = models.IntegerField(choices=SEX_CHOICES, default=1, verbose_name='性别') class Meta:
db_table = "student"

3.在drf_demo.urls.pydrf_app.urls.py中分别写入如下代码

# drf_demo.urls.py
urlpatterns = [
path('drf/', include('drf_app.urls')),
] # drf_app.urls.py
app_name = "drf_app"
urlpatterns = [
path('student/', views.student),
]

4.在settings.py文件的MIDDLEWARE中注释掉django.middleware.csrf.CsrfViewMiddleware,并在INSTALLED_APPS中加入2个app

'rest_framework',
'drf_app'

5.在命令行输入以下命令,将orm对象映射到数据库

python manage makemigrations
python manage migrate

6.写序列化类一般我们都在app项目中新建serializers.py文件,接下来可以正式编写序列化类了

序列化类编写

# Serializer的构造函数的参数:
# 1. instance:需要传递一个orm对象,或者是一个queryset对象,用来将orm转成json
# 2. data:把需要验证的数据传递给data,用来验证这些数据是不是符合要求
# 3. many:如果instance是一个queryset对象,那么就需要设置为True,否则为False class StudentSerializer(serializers.Serializer):
# 序列化提供给前台的字段个数由后台决定,可以少提供
# 但是提供的数据库对应的字段,名字一定要与数据库字段相同 id = serializers.IntegerField(read_only=True)
name = serializers.CharField(required=True, max_length=200)
sex = serializers.IntegerField(required=True)
age = serializers.IntegerField(required=True) def create(self, validated_data):
"""
根据提供的验证过的数据创建并返回一个新的`Student`实例
"""
return Student.objects.create(**validated_data) def update(self, instance, validated_data):
"""
根据提供的验证过的数据更新和返回一个已经存在的`Student`实例。
"""
instance.name = validated_data.get('name', instance.name)
instance.age = validated_data.get('name', instance.age)
instance.sex = validated_data.get('name', instance.sex)
instance.save()
return instance # 局部钩子 validate_要校验的字段名(self, 当前要校验字段的值)
def validate_name(self, value):
if 'j' in value.lower():
raise exceptions.ValidationError("名字非法")
return value def validate_sex(self, value):
if not isinstance(value, int):
raise exceptions.ValidationError("只能输入int类型")
if value != 1 and value != 2 :
raise exceptions.ValidationError("只能输入男和女")
return value # 全局钩子 validate(self, 系统与局部钩子校验通过的所有数据)
def validate(self, attrs):
age = attrs.get('age')
sex = attrs.get('sex')
if age < 22 and sex == 1:
raise exceptions.ValidationError({"age&sex": "男的必须22周岁以上才能结婚"})
return attrs

我们上面代码首先定义了序列化的字段,字段中的参数都继承自Field类,参数如下

def __init__(self, read_only=False, write_only=False,
required=None, default=empty, initial=empty, source=None,
label=None, help_text=None, style=None,
error_messages=None, validators=None, allow_null=False):
  • read_only:当为True时表示这个字段只能读,只有在返回数据的时候会使用。
  • write_only:当为True时表示这个字段只能写,只有在新增数据或者更新数据的时候会用到。比如我们的账号密码,只允许用户提交,后端是不返回密码给前台的
  • required:当为True时表示这个字段必填,不填状态码会返回400
  • default:默认值,没什么好说的
  • allow_null:当为True时,允许该字段的值为空

  之后我们又定义了局部钩子,校验特殊的字段,比如需求规定,用户的性别只能输入男和女,此时你就可以定义一个钩子,当然drf自动帮我们做了一些校验,比如需要的字段是int类型,你输入string类型,会自动触发系统的error,不需要我们额外定义,后面我们会进行测试

  接下来我们又定义了一个全局的钩子,意思就是针对整个数据进行校验,最适合的场景比如密码重复输入,一般我们注册的时候,需要输入2次密码,第二次用来确认,这个场景就适合用全局钩子

 

编写完serializers后,我们最后一步,编写视图函数,如下:

def student(request):
# 获取所有的学生
if request.method == "GET":
# 创建一个queryset对象
stu = Student.objects.all()
# 将对象序列化为dict
stu_data = StudentSerializer(instance=stu, many=True).data
return JsonResponse(status=200, data=stu_data, safe=False)
elif request.method == "POST":
data = JSONParser().parse(request)
serializer = StudentSerializer(data=data)
# 校验字段是否符合规范
if serializer.is_valid():
# 符合则保存到数据库
serializer.save()
return JsonResponse(data=serializer.data, status=200)
return JsonResponse(serializer.errors, status=400)

测试

测试分为GET请求和POST请求

GET请求

我们打开接口测试工具postman或者apifox,这里以apifox为例,输入127.0.0.1:8000/drf/student/,得到了以下结果

[
{
"id": 1,
"name": "jkc",
"sex": 1,
"age": 18
},
{
"id": 2,
"name": "mary",
"sex": 2,
"age": 20
}
]

说明序列化成功,成功地将数据库的数据通过json的格式返回给了前台

POST请求

同样打开接口工具,输入127.0.0.1:8000/drf/student/,在body中选择json格式,输入如下数据

{
"name": "aaaa",
"sex": 2,
"age": 18
}

运行结果如下:

{
"id": 13,
"name": "aaaa",
"sex": 2,
"age": 18
}

说明我们反序列化也成功了,小伙伴们自己实践时可以查看数据库,会多了一条这样的数据

接下来我们是否能触发钩子函数

测试validate_name钩子

输入测试数据

{
"name": "jjj",
"sex": 2,
"age": 18
}

返回结果如下:

{
"name": [
"名字非法"
]
}

测试validate_sex钩子

输入测试数据

{
"name": "kkk",
"sex": 3,
"age": 18
}

返回结果如下:

{
"sex": [
"只能输入男和女"
]
}

测试默认的输入类型错误

输入测试数据

{
"name": "kkk",
"sex": "???",
"age": 18
}

返回结果如下:

{
"sex": [
"请填写合法的整数值。"
]
}

测试默认的必填项不填

输入测试数据

{
"name": "kkk"
}

返回结果如下:

{
"sex": [
"该字段是必填项。"
],
"age": [
"该字段是必填项。"
]
}

测试全局钩子

输入测试数据

{
"name": "kkk",
"sex": 1,
"age": 18
}

返回结果如下:

{
"age&sex": [
"男的必须22周岁以上才能结婚"
]
}

总结

  1. 设置必填与选填序列化字段,设置校验规则
  2. 为需要额外校验的字段提供局部钩子函数,如果该字段不入库,且不参与全局钩子校验,可以将值取出校验
  3. 为有联合关系的字段们提供全局钩子函数,如果某些字段不入库,可以将值取出校验
  4. 重写create方法,完成校验通过的数据入库工作,得到新增的对象

Django(45)drf序列化类的使用(Serializer)的更多相关文章

  1. Django的DRF序列化方法

    安装rest_framework -- pip install djangorestframework -- 注册rest_framework序列化 -- Python--json -- 第一版 用v ...

  2. Django(46)drf序列化类的使用(ModelSerializer)

    前言 我们上篇文章使用到了Serializer类,可能有小伙伴说太过复杂,那么本篇就为大家带来更加简便的序列化类ModelSerializer ModelSerializer 先来看下ModelSer ...

  3. 067.Python框架Django之DRF视图类

    一 关于视图类的一下概念 drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. ...

  4. DRF框架(二)——解析模块(parsers)、异常模块(exception_handler)、响应模块(Response)、三大序列化组件介绍、Serializer组件(序列化与反序列化使用)

    解析模块 为什么要配置解析模块 1)drf给我们提供了多种解析数据包方式的解析类 form-data/urlencoded/json 2)我们可以通过配置来控制前台提交的哪些格式的数据后台在解析,哪些 ...

  5. DRF 序列化组件

    Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...

  6. django rest_framework Serializers 序列化组件

    为什么要用序列化组件 当我们做前后端分离的项目~~我们前后端交互一般都选择JSON数据格式,JSON是一个轻量级的数据交互格式. 那么我们给前端数据的时候都要转成json格式,那就需要对我们从数据库拿 ...

  7. [Django REST framework - 序列化组件、source、钩子函数]

    [Django REST framework - 序列化组件.source.钩子函数] 序列化器-Serializer 什么是rest_framework序列化? 在写前后端不分离的项目时: 我们有f ...

  8. 写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用

    写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用 一.了解什么是DRF DRF: Django REST framework Django REST framew ...

  9. python 全栈开发,Day95(RESTful API介绍,基于Django实现RESTful API,DRF 序列化)

    昨日内容回顾 1. rest framework serializer(序列化)的简单使用 QuerySet([ obj, obj, obj]) --> JSON格式数据 0. 安装和导入: p ...

随机推荐

  1. Java 常用类总结(SE基础)

    本篇博客对java常用类相关知识进行了归纳总结,比较详细,适用于学习和复习. 1. 字符串相关的类 1.1 String String是一个final类,代表不可变的字符序列.不可被继承. Strin ...

  2. Weekly Contest 184

    1408. String Matching in an Array Given an array of string words. Return all strings in words which ...

  3. 使用 WinAFL 图片解析软件进行模糊测试 - FreeImage 图片解析库

    看雪链接:https://bbs.pediy.com/thread-255162.htm

  4. SpringJUnit4ClassRunner requires JUnit 4.12 or higher

    报错:需要Junit 4.12 或者更高的版本 原因:查看pom.xml文件引入的Junit版本为4.11 解决办法:修改Junit版本为4.12即可

  5. Java发送邮件报错:com.sun.mail.util.LineOutputStream.<init>(Ljava/io/OutputStream;Z)V

    在练习使用Java程序发送邮件的代码 运行出现了com.sun.mail.util.LineOutputStream.<init>(Ljava/io/OutputStream;Z)V报错信 ...

  6. Yii2表头强制不换行

    在Yii2中使用GridView生成的表格有一个小问题,那就是表头的列宽是根据列的值自适应的,但有时值的长度比较小,表头就会出现下面这种情况(表头不在同一行,非常的不利于数据的查看) 设置强制不换行可 ...

  7. SQL必知必会 —— 性能优化篇

    数据库调优概述 数据库中的存储结构是怎样的 在数据库中,不论读一行,还是读多行,都是将这些行所在的页进行加载.也就是说,数据库管理存储空间的基本单位是页(Page). 一个页中可以存储多个行记录(Ro ...

  8. 有趣的css—简单的下雨效果2.0版

    简单的下雨效果2.0版 前言 笔者上一篇发布的文章有趣的css-简单的下雨效果中有位老哥给我提了一个很棒的建议,大致意思是波纹应该产生于雨滴的消失处. 这是按照老哥的建议完善后的效果图: 由于我制作G ...

  9. Codeforces Round #661 (Div. 3)

    A. Remove Smallest 题意:数组是否满足任意i,j保证|ai-aj|<=1,如果都可以满足,输出YES,否则输出NO 思路:直接排序遍历即可 代码: 1 #include< ...

  10. netcore3.1 webapi使用signalR

    前言 今天尝试了一下signalR,感觉还不错,因为暂时用不到,就写一篇博文来记录搭建过程,以免以后给忘了,基于官方文档写的,不过官方没有webapi调用例子,就自己写了一下,大神勿喷 使用 1.创建 ...