1 序列化器-Serializer
1# 序列化器的作用
21. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
32. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
43. 反序列化,完成数据校验功能
2 序列化器的序列化
2.1 基本使用
2.1.1 视图层views.py
1from django.shortcuts import render
2
3# Create your views here.
4
5
6# def test(request):
7# request.session['name']='lqz'
8
9
10#### 查询所有图书的视图类
11from rest_framework.views import APIView
12from app01.models import Book # 绝对导入
13
14# from .models import Book # 相对导入,用了相对导入,当前py文件,不能以脚本形式运行
15from .serializer import BookSerializer
16from rest_framework.response import Response
17
18
19# 针对于某个表模型,总共5个接口
20# 获取所有 get
21# 获取单个 get
22# 删除单个 delete
23# 修改单个 update
24# 新增单个 post
25
26# 以后你写的所有接口(跟数据库相关),都是这个5个或这5个的变形
27class BookView(APIView):
28 def get(self, request, *args, **kwargs):
29 # 查询出所有图书
30 books = Book.objects.all()
31 # 把qs对象序列化成字典,使用序列化类完成序列化
32 # instance=None, 是要序列化的对象(可以是单个对象,可以是多个对象(放到列表或者qs对象),一定要写many=True)
33 # data=empty 反序列化的字典,目前还没用到
34 print(books)
35 ser = BookSerializer(instance=books, many=True) # 传入要序列化的数据
36 print(ser.data)
37 # 返回给前端 ser.data 是个字典
38 # 如果是浏览器,会有一个好看的页面(注册app),如果是postman,就是json格式
39 return Response(data=ser.data)
40
41 # 新增
42 def post(self, request, *args, **kwargs):
43 # 前端传入的数据,在request.data中,是个字典
44 # 如果不使用序列化类,如何保存
45 # book=Book(title=request.data.get('title'))
46 # book.save()
47
48 # 使用序列化类做保存
49 ser = BookSerializer(data=request.data)
50 # 数据校验:如果是True,表示校验通过,直接保存
51 if ser.is_valid():
52 ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
53 return Response(ser.data) # 又做了一次序列化,返回给了前端
54 else:
55 return Response(ser.errors)
56
57
58class BookDetailView(APIView):
59 def get(self, request, pk):
60 # 查询某一本图书
61 books = Book.objects.all().filter(pk=pk).first()
62 ser = BookSerializer(instance=books) # 传入要序列化的数据
63
64 return Response(data=ser.data)
65
66 def delete(self, request, pk):
67 # 跟序列化类没有关系
68 Book.objects.all().filter(pk=pk).delete()
69 return Response()
70
71 def put(self, request, pk):
72 book = Book.objects.filter(pk=pk).first()
73
74 ser = BookSerializer(instance=book, data=request.data)
75 # 数据校验:如果是True,表示校验通过,直接保存
76 if ser.is_valid():
77 ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写update方法
78 return Response(ser.data) # 又做了一次序列化,返回给了前端
2.1.2 序列化器serializer.py
1# 写序列化类
2from rest_framework import serializers
3from .models import Book
4from rest_framework.exceptions import ValidationError
5
6
7class BookSerializer(serializers.Serializer): # 一定要继承一个序列化的基类
8 # 写字段,你想序列化哪个字段,就写哪个
9 title = serializers.CharField(max_length=8, min_length=3)
10 price = serializers.IntegerField()
11 # pub_date = serializers.DateField()
12
13 publish = serializers.CharField()
14
15 # 重写create,使它能够支持新增保存 (派生)
16 def create(self, validated_data): # validated_data校验过后的数据
17 book = Book.objects.create(**validated_data)
18 return book # 一定不要忘了return 对象,否则在视图类中用ser.data 就报错了
19
20 # 重写 update 支持修改
21 def update(self, instance, validated_data):
22 instance.title = validated_data.get('title')
23 instance.price = validated_data.get('price')
24 instance.publish = validated_data.get('publish')
25 instance.save()
26 return instance
27
28 # validate_字段名 先走字段自己的,再走局部钩子
29 def validate_title(self, item):
30 print(item)
31 # 校验字段,不能以sb开头
32 if item.startswith('sb'):
33 raise ValidationError('不能以sb开头')
34
35 return item
36
37 # 全局钩子
38 def validate(self, attrs):
39 # 校验失败,抛异常
40 if attrs.get('title') == attrs.get('publish'):
41 raise ValidationError('标题和出版社不能一样')
42
43 return attrs
2.1.3 表模型 models.py
1from django.db import models
2
3
4# Create your models here.
5
6
7class Book(models.Model):
8 title = models.CharField(max_length=32,default='红')
9 price = models.IntegerField(default='0')
10 # pub_date = models.DateField() # sqlite对日期的处理有问题,换成mysql
11 publish = models.CharField(max_length=32,default='出')
2.1.4 路由urls.py
1from app01 import views
2urlpatterns = [
3 path('admin/', admin.site.urls),
4 path('books/', views.BookView.as_view()),
5 path('books/<int:pk>', views.BookDetailView.as_view()),
6]
2.2 常用字段
1BooleanField BooleanField()
2NullBooleanField NullBooleanField()
3CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
4EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
5RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
6SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
7URLField URLField(max_length=200, min_length=None, allow_blank=False)
8UUIDField 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"
9IPAddressField IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
10IntegerField IntegerField(max_value=None, min_value=None)
11FloatField FloatField(max_value=None, min_value=None)
12DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
13DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
14DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
15TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
16DurationField DurationField()
17ChoiceField ChoiceField(choices) choices与Django的用法相同
18MultipleChoiceField MultipleChoiceField(choices)
19FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
20ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
21ListField ListField(child=, min_length=None, max_length=None)
22DictField DictField(child=)
2.3 常用字段参数
1#参数名称 作用
2max_length 最大长度
3min_lenght 最小长度
4
5
6allow_blank 是否允许为空
7trim_whitespace 是否截断空白字符
8
9max_value 最小值
10min_value 最大值
11
12
13#通用参数:(针对所有字段)
14
15参数名称 说明
16#非常重要
17read_only 表明该字段仅用于序列化输出,默认False
18write_only 表明该字段仅用于反序列化输入,默认False
19
20
21
22required 表明该字段在反序列化时必须输入,默认True
23default 反序列化时使用的默认值
24allow_null 表明该字段是否允许传入None,默认False
25validators 该字段使用的验证器
26error_messages 包含错误编号与错误信息的字典
3 序列化器的反序列化
3.1 基本使用
1 def post(self, request, *args, **kwargs):
2 # 前端传入的数据,在request.data中,是个字典
3 # 如果不使用序列化类,如何保存
4 # book=Book(title=request.data.get('title'))
5 # book.save()
6
7 # 使用序列化类做保存
8 ser = BookSerializer(data=request.data)
9 # 数据校验:如果是True,表示校验通过,直接保存
10 if ser.is_valid():
11 ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
12 return Response(ser.data) # 又做了一次序列化,返回给了前端
13 else:
14 return Response(ser.errors)
1 def put(self, request, pk):
2 book = Book.objects.filter(pk=pk).first()
3
4 ser = BookSerializer(instance=book, data=request.data)
5 # 数据校验:如果是True,表示校验通过,直接保存
6 if ser.is_valid():
7 ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写update方法
8 return Response(ser.data) # 又做了一次序列化,返回给了前端
3.2 数据校验
1# 字段自己校验规则
2title = serializers.CharField(max_length=8, min_length=3)
3
4# 局部钩子
5# validate_字段名 先走字段自己的,再走局部钩子
6 def validate_title(self, item):
7 print(item)
8 # 校验字段,不能以sb开头
9 if item.startswith('sb'):
10 raise ValidationError('不能以sb开头')
11
12 return item
13# 全局钩子
14 def validate(self, attrs):
15 # 校验失败,抛异常
16 if attrs.get('title') == attrs.get('publish'):
17 raise ValidationError('标题和出版社不能一样')
18
19 return attrs
4 模型类序列化器ModelSerializer
1# 反序列化,正常情况不需要重写 create和update
2# 序列化:跟表模型有对应关系,不需要一个个字段都写了
3
4
5
6
7# class BookModelSerializer(serializers.ModelSerializer):
8# # 跟某个表模型建立关系
9# class Meta:
10# model = Book # 跟哪个表建立关系
11# fields = ['title','price','id','publish'] # 要序列化哪些字段
12# # fields = '__all__' # 所有字段都序列化
13#
14#
15# # 了解
16# # exclude=['title'] # 除了某个字段外
17# # depth=1 # 表关联
18#
19#
20#
21# #重点
22#
23# # read_only 只读,只序列化
24#
25# # write_only
26#
27# # 重写某个字段
28# title=serializers.CharField(max_length=8,min_length=3)
29#
30# # 局部和全局钩子跟之前一模一样
31#
32# def validate_price(self, price):
33# if not price>100:
34# raise ValidationError('价格必须大于100')
35#
36# return price
37
38
39class BookModelSerializer(serializers.ModelSerializer):
40 # 跟某个表模型建立关系
41 class Meta:
42 model = Book # 跟哪个表建立关系
43 fields = ['title', 'price', 'id', 'publish'] # 要序列化哪些字段
44 # 重点
45 # 额外给某些字段传参数
46 # extra_kwargs = {
47 # 'title': {'max_length': 8, 'min_length': 3},
48 # 'price': {'min_value': 100}
49 # }
50
51 # read_only 只读,只序列化
52 # write_only 只写,只做反序列化,这个字段不做序列化
53 extra_kwargs = {
54 'title': {'read_only': True},
55 # 'price': {'write_only': True}
56 }