赞
踩
目录
序列化类(组件)可以干的事:
1 写个py文件,叫serializer.py
2 写个类,继承serializers.Serializer
3 在类中写要序列化的字段
from rest_framework import serializers class PublishSerializer(serializers.Serializer): # 写字段,要序列化的字段 name = serializers.CharField() addr = serializers.CharField() id = serializers.IntegerField()4 在视图类中使用,完成序列化
多条 ser = PublishSerializer(instance=publish_list, many=True) ser.data # 序列化后的数据 单条: ser = PublishSerializer(instance=publish) ser.data # 序列化后的数据
视图类
- from .serializer import PublishSerializer
-
-
- class PublishView(APIView):
- def get(self, request):
- publish_list = Publish.objects.all()
- ser = PublishSerializer(instance=publish_list, many=True)
- # 如果序列化多条,要many=True
- return Response({'code': 100, 'msg': '查询所有成功', 'results': ser.data})
-
- class PublishDetailView(APIView):
- def get(self, request, pk):
- publish = Publish.objects.filter(pk=pk).first()
- ser = PublishSerializer(instance=publish) # 单个不写many=True
- return Response(
- {'code': 100, 'msg': '查询单条成功', 'results': ser.data})

序列化类
- from rest_framework import serializers
- class PublishSerializer(serializers.Serializer):
- # 写字段,要序列化的字段
- name = serializers.CharField()
- # addr = serializers.CharField()
- id = serializers.IntegerField()
路由
- urlpatterns = [
- path('publish/', views.PublishView.as_view()),
- path('publish/<int:pk>', views.PublishDetailView.as_view()),
- ]
序列化类可以做字段校验---> 三层
第一层:字段自己的serializers.CharField(max_length=12,min_length=3)
第二层:局部钩子
- def validate_name(self, name):
- # 待校验的前端传入的name的数据
- if name.startswith("sb"):
- # 不行,抛异常
- raise ValidationError('不能以sb开头')
- return name
全局钩子--> 前端多传的,这里不会有
- def validate(self, attrs):
- print(attrs)
- # 多个字段同时校验
- # 出版社名和地址不能一样---》出版社前3个字不能和地址前3个字一样
- if attrs.get('name')[:3] == attrs.get('addr')[:3]:
- raise ValidationError('出版社名和地址不能一样')
- return attrs
写序列化类:写三层规则
视图类中:
- ser = PublishSerializer(data=request.data) # 把待校验数据传入
- if ser.is_valid(): # 做数据校验---> 三层
- print(ser.data)
- else:
- print(ser.errors) # 没有校验通过,打印错误信息
1 在序列化类中,必须重写 create,完成真正的保存
- """保存,必须重写create"""
- def create(self, validated_data):
- # validated_data 校验过后的数据---》多传的数据,在这没有
- publish = Publish.objects.create(**validated_data)
- return publish
- # 不要忘了返回新增的对象---> 后续会拿着这个对象做序列化 ser.data--->根据它做序列化的
2 在视图类中,数据校验通过后,调用ser.save()
ser.save() # 使用序列化类保存--> 会报错---> 我们没有指定保存到那个表--> 必须重写create方法
修改功能,也要校验和保存
1 在序列化类中,必须重写 update,完成真正的修改
- def update(self, instance, validated_data): # {name:上海出版社,add:上海地址}
- instance.name = validated_data.get('name')
- instance.addr = validated_data.get('addr')
- instance.save() # publish 对象的save---> 保存到数据中
- return instance
2 视图类中
ser = PublishSerializer(instance=publish, data=request.data)
ser.save() # 虽然新增或修改都是调用save,但是内部做了判断
字段 | 字段构造方式 | 详解 |
---|---|---|
BooleanField | BooleanField() | 布尔字段用于存储和表示真/假值。构造方法不需要参数。 |
NullBooleanField | NullBooleanField() | 可空布尔字段是可以接受三个值的布尔字段:True、False和None(空值)。构造方法不需要参数。 |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) | 字符字段用于存储短文本数据。max_length指定字符的最大长度,min_length指定最小长度。allow_blank指定是否允许为空值。trim_whitespace指定是否在保存数据前去除首尾的空格。 |
EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) | Email字段用于存储和验证电子邮件地址。max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值。 |
RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) | 正则表达式字段用于存储和验证符合特定模式的数据。regex指定正则表达式,max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值 |
SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+ | Slug字段用于存储URL友好的文本标识符。max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值。 |
URLField | URLField(max_length=200, min_length=None, allow_blank=False) | URL字段用于存储和验证URL地址。max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值。 |
UUIDField | 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" | UUID字段用于存储和验证通用唯一标识符。format参数指定UUID的格式。 |
IPAddressField | IPAddressField(protocol=’both’, unpack_ipv4=False, **options) | IP地址字段用于存储和验证IP地址。protocol参数指定所允许的IP地址协议类型,unpack_ipv4参数指定是否拆分IPv4地址。 |
IntegerField | IntegerField(max_value=None, min_value=None) | 整数字段用于存储整数值。max_value指定最大值,min_value指定最小值。 |
FloatField | FloatField(max_value=None, min_value=None) | 浮点数字段用于存储浮点数值。max_value指定最大值,min_value指定最小值。 |
DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 | 十进制字段用于存储精确的十进制数值。max_digits指定最多位数,decimal_places指定小数点位置。coerce_to_string指定是否将值强制转化为字符串形式。max_value指定最大值,min_value指定最小值。 |
DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) | 日期时间字段用于存储日期和时间。format参数指定日期时间的输出格式,input_formats参数指定输入格式。 |
DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) | 日期字段用于存储日期。format参数指定日期的输出格式,input_formats参数指定输入格式。 |
TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) | 时间字段用于存储时间。format参数指定时间的输出格式,input_formats参数指定输入格式。 |
DurationField | DurationField() | 持续时间字段用于存储一段时间的持续时间。构造方法不需要参数。 |
ChoiceField | ChoiceField(choices) choices与Django的用法相同 | 选择字段用于存储和验证预定义选项中的一个值。choices参数指定可选的选项值。 |
MultipleChoiceField | MultipleChoiceField(choices) | 多选字段用于存储和验证多个预定义选项中的值。choices参数指定可选的选项值。 |
FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) | 文件字段用于上传和保存文件。max_length指定文件名的最大长度,allow_empty_file指定是否允许为空文件。use_url指定是否使用文件的URL路径。 |
ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) | 图片字段用于上传和保存图片文件。max_length指定文件名的最大长度,allow_empty_file指定是否允许为空文件。use_url指定是否使用图片的URL路径。 |
ListField | ListField(child=, min_length=None, max_length=None) | 列表字段用于存储和验证列表类型的数据。child参数指定列表中元素的类型,min_length指定最小长度,max_length指定最大长度。 |
DictField | DictField(child=) | 字典字段用于存储和验证字典类型的数据。child参数指定字典中value的类型。 |
- IntegerField
- CharField
- DateTimeField
- DecimalField
-
- ListField和DictField
(1) 选项参数:(CharField,IntegerField)
参数名称 | 作用 |
---|---|
max_length | 校验,最大长度 |
min_lenght | 检验,最小长度 |
allow_blank | 是否允许为空 |
trim_whitespace | 去掉前后的空白 |
max_value | 最小值 |
min_value | 最大值 |
(2) 通用参数
- read_only 表明该字段仅用于序列化输出,默认False
- write_only 表明该字段仅用于反序列化输入,默认False
- -------------------------------------------------------
- required 表明该字段在反序列化时必须输入,默认True
- default 反序列化时使用的默认值
- allow_null 表明该字段是否允许传入None,默认False
- validators 该字段使用的验证器:validators=[方法],方法对该字段做校验
- error_messages 包含错误编号与错误信息的字典
- ---------------
- label 用于HTML展示API页面时,显示的字段名称
- help_text 用于HTML展示API页面时,显示的字段帮助提示信息
- read_only
- write_only
1 修改字段,映射字段
- # publish_name表中不存在
- publish_name = serializers.CharField(source='name')
2 修改字段,映射方法
- # sb_name是表模型中一个方法
- name = serializers.CharField(source='sb_name')
3 修改字段,跨表查询
- # book表中可以链表查询
- publish=models.ForeignKey(to='Publish.name')
- # 定制序列化返回的字段格式
- -方案一:在表模型中写,在序列化类中映射 (可以使用source)
- # models.py
- def publish_detail(self):
- return {'name': self.publish.name, 'city': self.publish.city}
- # serializer.py
- publish_detail = serializers.DictField()
- # 前端看到
- "publish_detail": {
- "name": "北京出版社",
- "city": "北京"
- }
- -方案二:在序列化类中写SerializerMethodField,必须配合一个方法 get_字段名,方法返回什么,前端就看到什么
- # Serializer.py
- publish_detail = serializers.SerializerMethodField()
- def get_publish_detail(self, obj):
- return {'name': obj.publish.name, 'city': obj.publish.city}
- # 前端看到
- "publish_detail": {
- "name": "北京出版社",
- "city": "北京"
- }

models.py
- from django.db import models
-
-
- class Book(models.Model):
- name = models.CharField(max_length=32)
- price = models.DecimalField(max_digits=5, decimal_places=2)
-
- publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
- authors = models.ManyToManyField(to='Author')
-
- def __str__(self):
- return self.name
- # def book_name(self):
- # return self.name+'sb'
- # def publish_detail(self):
- # return {'name': self.publish.name, 'city': self.publish.city}
- #
- # def author_list(self):
- # l = []
- # for author in self.authors.all():
- # l.append({'name': author.name, 'age': author.age})
- # return l
-
-
- class Author(models.Model):
- name = models.CharField(max_length=32)
- age = models.IntegerField()
- author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
-
- def __str__(self):
- return self.name
-
-
- class AuthorDetail(models.Model):
- telephone = models.BigIntegerField()
- birthday = models.DateField()
- addr = models.CharField(max_length=64)
-
-
- class Publish(models.Model):
- name = models.CharField(max_length=32)
- city = models.CharField(max_length=32)
- email = models.EmailField()
-
- def __str__(self):
- return self.name
-
- class Meta:
- verbose_name = '出版社'
- verbose_name_plural = verbose_name

views.py
- class BookView(APIView):
- def get(self, request):
- obj = Book.objects.all()
- ser = BookSerializer(instance=obj, many=True)
-
- '''
- [
- {
- "name": "西游记",
- "price": "66.00",
- "publish_detail": {name:名字,city:城市},
- "authors_list":[{name:名字,age:19}]
- },
-
- ]
-
- '''
- return Response(ser.data)

- ### 定制返回字段 ###
- class BookSerializer(serializers.Serializer):
- name = serializers.CharField()
- price = serializers.CharField()
- # 定制返回字段---》方案一:在表模型中写方法,在序列化类中做映射
- # publish_detail = serializers.CharField() # publish_detail 会映射表模型中 publish_detail方法,方法返回值是 字典,强行用CharField字符串接收
- # publish_detail = serializers.DictField() # publish_detail 会映射表模型中 publish_detail方法,方法返回值是 字典,用DictField接收
- # author_list = serializers.ListField()
-
- # 定制返回字段---》方案二:在序列化类中写 SerializerMethodField
- # 只要写了这个字段类SerializerMethodField,必须配合一个方法:get_字段名,这个方法返回什么,前端这个字段就显示什么
- publish_detail = serializers.SerializerMethodField()
-
- def get_publish_detail(self, obj):
- # 当前序列化到的book对象
- return {'name': obj.publish.name, 'city': obj.publish.city}
-
- author_list = serializers.SerializerMethodField()
-
- def get_author_list(self, obj):
- l = []
- for author in obj.authors.all():
- l.append({'name': author.name, 'age': author.age})
- return l
-
- book_name = serializers.SerializerMethodField()
-
- def get_book_name(self, obj):
- return obj.name + 'sb'

反序列化保存
使用同一个序列化类会出现
serializer.py
- class BookSerializer(serializers.Serializer):
- name = serializers.CharField() # 公共的
- price = serializers.CharField() # 公共的
- publish = serializers.IntegerField(write_only=True) # 只用来做反序列化
- authors = serializers.ListField(write_only=True) # 只用来做反序列化
-
- publish_detail = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
- author_list = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
-
- def get_publish_detail(self, obj):
- return {'name': obj.publish.name, 'city': obj.publish.city}
-
- def get_author_list(self, obj):
- l = []
- for author in obj.authors.all():
- l.append({'name': author.name, 'age': author.age})
- return l
-
- def create(self, validated_data):
- # {name,price,publish:1,authors:[1,2]}
- authors = validated_data.pop('authors')
- book = Book.objects.create(name=validated_data.get('name'), price=validated_data.get('price'),
- publish_id=validated_data.get('publish'))
- book.authors.add(*authors)
- return book
-
- def update(self, instance, validated_data):
- # {name,price,publish:1,authors:[1,2]}
- authors = validated_data.pop('authors')
- validated_data['publish_id'] = validated_data.pop('publish')
- for key in validated_data:
- setattr(instance, key, validated_data[key])
-
- instance.save()
- # 先清空在放入
- # instance.authors.clear()
- # instance.authors.add(*authors)
- # 直接存
- instance.authors.set(authors)
- return instance

views.py
- class BookView(APIView):
-
- def post(self, request):
- ser = BookSerializer(data=request.data)
- if ser.is_valid():
- ser.save()
- return Response(ser.data)
- else:
- return Response(ser.errors)
-
-
- class BookDetail(APIView):
- def put(self, request, pk):
- book = Book.objects.filter(pk=pk).first()
- ser = BookSerializer(instance=book, data=request.data)
- if ser.is_valid():
- ser.save()
- return Response(ser.data)
- else:
- return Response(ser.errors)

urls.py
- urlpatterns = [
- path('books/', views.BookView.as_view()),
- path('books/<int:pk>/', views.BookDetail.as_view()),
- ]
注:多表反序列化校验 --> 跟之前一样
之前写的序列化类,继承了serializers.Serializer,跟表没有必然联系
ModelSerializer跟表一一对应,以后基本需要重写create和update
serializer.py
- ### 继承ModelSerializer --->少写代码
- class BookSerializer(serializers.ModelSerializer):
- # name = serializers.CharField(max_length=18,min_length=3) # 公共的
- # price = serializers.CharField() # 公共的
- # publish = serializers.IntegerField(write_only=True) # 只用来做反序列化
- # authors = serializers.ListField(write_only=True) # 只用来做反序列化
- # 上述操作,通过 Meta实现了
-
- # 扩写的字段,也要在fields注册
- # 方式二:定制字段
- # publish_detail = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
- # author_list = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
- # def get_publish_detail(self, obj):
- # return {'name': obj.publish.name, 'city': obj.publish.city}
- # def get_author_list(self, obj):
- # l = []
- # for author in obj.authors.all():
- # l.append({'name': author.name, 'age': author.age})
- # return l
-
- # 方式二:定制字段方式一
- # publish_detail = serializers.DictField(read_only=True)
- # author_list = serializers.ListField(read_only=True)
- class Meta:
- model = Book # 写了这两句,会把表模型中Book,所有字段映射过来
- # fields='__all__'
- fields = ['name', 'price', 'publish', 'authors', 'publish_detail', 'author_list']
- extra_kwargs = { # 给某个或某几个字段设置字段属性
- 'name': {'max_length': 18, 'min_length': 3},
- 'publish': {'write_only': True},
- 'authors': {'write_only': True},
- 'publish_detail': {'read_only': True},
- 'author_list': {'read_only': True},
- }
-
- # 一般不需要写create和update了---> ModelSerializer帮我们实现了
- # 局部钩子和全局钩子,该怎么写还怎么写
- # def validate_name(self,name):
- # pass

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。