序列化组件

序列化组件的三大功能

  1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串

    成都创新互联公司专注于企业全网营销推广、网站重做改版、资阳网站定制设计、自适应品牌网站建设、H5建站电子商务商城网站建设、集团公司官网建设、成都外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为资阳等各大城市提供网站开发制作服务。

  2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型

  3. 反序列化时同时会完成数据校验功能

序列化器Serializer使用方法

查询单个数据语法:

1.在setting.py中的app配置里注册一下drf

2.在django的模型层创建一个表

from django.db import models

# Create your models here.
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    author = models.CharField(max_length=32)

3.在表中添加一些数据

4.编写序列化组件(类似forms组件),可以在应用下单独创一个文件夹,里面放序列化组件.py

from rest_framework import serializers#  导入drf中的序列化类

# 创建一个类继承Serializer序列化类
class BookSerializer(serializers.Serializer):
    # 定义需要序列化的字段,想要哪个字段就添加该字段,不需要就注释掉
    nid = serializers.CharField()
    name = serializers.CharField()
    price = serializers.CharField()

5.在url.py中开设路径获取序列化之后的数据

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'^book/(?P\d+)/$',views.BooksView.as_view()) #CBV格式的url
]

6.在视图函数中序列化需要的模型对象,返回给前端页面字典格式的数据

from rest_framework.views import APIView  # 导入drf模块的apiview,使得cbv格式的视图函数继承它
from app01 import models
from .ser import BookSerializer # 导入自己写好的序列化组件
from rest_framework.response import Response # 导入drf模块的响应类

class BooksView(APIView):
    # get请求的视图函数
    def get(self,request,pk):
        # 得到需要查询的模型对象
        book = models.Book.objects.filter(pk=pk).first()
        # 将模型对象交给自己写好的序列化器,生成一个序列化对象
        book_ser = BookSerializer(book)
        # book_ser.data 序列化对象.data就是序列化后的字典
        return Response(book_ser.data) # 利用drf中的Response类返回给前端,Response会帮您把这个字典序列化成json格式!
        # 使用JsonResponse返回上述字典,在浏览器就没有Response漂亮的格式而已,也是返回json数据格式
        return JsonResponse(book_ser.data,json_dumps_params={'ensure_ascii':False})

查询所有语法:

# views.py
class BooksView(APIView):
    def get(self,request):
        response_msg = {'status': 100, 'msg': '成功'}
        books=Book.objects.all()
        book_ser=BookSerializer(books,many=True)  #序列化多条,如果序列化一条,不需要写
        response_msg['data']=book_ser.data
        return Response(response_msg)
    
#urls.py
path('books/', views.BooksView.as_view()),

修改数据语法

1.在cbv格式的视图函数中添加put函数

    def put(self,request,pk):
        back_dic = {'code':1000,'msg':'成功'}
        # 1.得到需要查询的模型对象
        book = models.Book.objects.filter(pk=pk).first()
        # 2. 将模型对象交给自己写好的序列化器,生成一个序列化对象,除了传模型对象,还需要传入用户修改的数据
        book_ser = BookSerializer(instance=book,data=request.data)
        # 3.进行数据校验,类似forms组件的校验
        is_right = book_ser.is_valid()
        if is_right:
            # 4.校验通过操作序列化对象保存修改数据
            book_ser.save() # 注意这里需要在序列化组件中重写update()方法,否则报错
            # 5.将正确的数据在返回给前端
            back_dic['data'] = book_ser.data
        else:
            back_dic['code'] = 1001
            back_dic['msg'] = '数据格式不正确'
            back_dic['data'] = book_ser.errors
        return Response(back_dic)

2.在自定义的序列化组件类中添加update()方法

    def update(self, instance, validated_data):
        # instance参数就是book这个对象,validated_data就是用户修改提交上来的字典格式数据
        # 1.修改这个对象的字段值
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        # 2.操作数据库保存修改数据
        instance.save() # 相当于book.save() 是django orm提供的方法
        # 最后需要把这个book对象在返回出去
        return instance

新增数据语法

# views.py
class BooksView(APIView):

    # 新增
    def post(self,request):
        response_msg = {'status': 100, 'msg': '成功'}
        #修改才有instance,新增没有instance,只有data
        book_ser = BookSerializer(data=request.data)
        # book_ser = BookSerializer(request.data)  # 这个按位置传request.data会给instance,就报错了
        # 校验字段
        if book_ser.is_valid():
            book_ser.save()
            response_msg['data']=book_ser.data
        else:
            response_msg['status']=102
            response_msg['msg']='数据校验失败'
            response_msg['data']=book_ser.errors
        return Response(response_msg)
#ser.py 序列化类重写create方法
    def create(self, validated_data):
        instance=Book.objects.create(**validated_data)
        return instance
# urls.py
path('books/', views.BooksView.as_view()),

删除数据语法:

# views.py
class BookView(APIView):
    def delete(self,request,pk):
        ret=Book.objects.filter(pk=pk).delete()
        return Response({'status':100,'msg':'删除成功'})
# urls.py
re_path('books/(?P\d+)', views.BookView.as_view()),

序列化的字段类型

常用字段类型

# BooleanField	BooleanField()
# NullBooleanField	NullBooleanField()
# CharField	CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
# EmailField	EmailField(max_length=None, min_length=None, allow_blank=False)
# RegexField	RegexField(regex, max_length=None, min_length=None, allow_blank=False)
# SlugField	SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
# URLField	URLField(max_length=200, min_length=None, allow_blank=False)
# UUIDField	UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee0fb31a" 3)'int' - 如: "" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-fb31a"
# IPAddressField	IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
# IntegerField	IntegerField(max_value=None, min_value=None)
# FloatField	FloatField(max_value=None, min_value=None)
# DecimalField	DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
# DateTimeField	DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
# DateField	DateField(format=api_settings.DATE_FORMAT, input_formats=None)
# TimeField	TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
# DurationField	DurationField()
# ChoiceField	ChoiceField(choices) choices与Django的用法相同
# MultipleChoiceField	MultipleChoiceField(choices)
# FileField	FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
# ImageField	ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

需要记住的字段类型

CharField
BooleanField
IntegerField
DecimalField
ListField
DictField

常用的字段参数

1 给CharField字段类使用的参数
    max_length        最长长度
    min_length        最小长度
    allow_blank       是否允许为空
    trim_whitespace   是否截断空白字段

2 给IntegerField字段类使用的参数
    max_value         最小值
    min_value         最大值

3 通用参数,放在哪个字段类上都可以
    required          表明该字段在反序列化时必须输入,默认True
    default           反序列化时使用的默认值
    allow_null        表明该字段是否允许传入None,默认False
    validators        该字段使用的验证器
    error_messages    包含错误编码与错误信息的字典
    label             用于HTML展示API页面时,显示的字段名称
    help_text         用于Html展示API页面时,显示的字段帮助提示信息

4 重点
read_only	表明该字段仅用于序列化输出,默认False,如果设置成True,postman中可以看到该字段,修改时,不需要传该字段
write_only	表明该字段仅用于反序列化输入,默认False,如果设置成True,postman中看不到该字段,修改时,该字段需要传

序列化组件中的钩子函数和validators校验

局部钩子:

    # 序列化组件中的钩子函数
    # 局部钩子函数validate_字段名的形式,需要传入一个data参数,data就是price
    def validate_price(self, data):
        print(type(data)) #格式为
        print(data) # 34.00
        # 进行校验,当价格大于30报错
        if float(data) < 30:
            return data
        else:
            # 校验不通过,抛出异常 rest_framework异常在 from rest_framework.exceptions import ValidationError里
            raise ValidationError('价格太高')

全局钩子:

    def validate(self,validated_data): # validated_data校验之后的数据
        name = validated_data.get('name')
        price = validated_data.get('price')
        if name == 'zhang' and price == '25':
            raise ValidationError('不正确')
        return validated_data

第三种validators校验:

# 定义一个函数
def check_name(data):
    if data.startswith('sb'):
        raise ValidationError('名字不能是sb开头')
    else:
        return data

# 在指定字段内添加validators
name = serializers.CharField(validators=[check_name])   #validators=[]列表中写函数的内存地址

总结:主要用局部钩子和全局钩子!!

模型类序列化器

# 模型化序列器,继承ModelSerializer,并且不需要自己书写updata和create方法了
class BookSerializer2(serializers.ModelSerializer):
    # 1.定义一个Meta类
    class Meta:
        # 2.model后面等于需要序列化的表
        model = models.Book
        # 3.表示序列化该表中所有的字段
        # fields = '__all__'
        # 4.序列化表中的指定字段
        # fields = ('name','price') # 注意fields里可以放model.py里book表对应的字段,也可以放book表类里定义的方法(详解下图)
        # 5.序列化除以下字段
        exclude = ('name',) # ()里是一个元组,注意需要加个逗号
        # 6.read_only和write_only这些原本需要在字段括号内书写的参数都放在extra_kwargs里书写
        extra_kwargs = {
            'price':{'write_only':True},
        }


在book表类里加的publish_name方法,fields里放该方法,会返回该方法的返回值!

视图函数部分:

class BooksView2(APIView):
    def get(self,request):
        books = models.Book.objects.all()
        book_ser = BookSerializer2(books,many=True) # 这里改成了BookSerializer2模型化序列器
        return Response(book_ser.data)

自己封装的返回给前端的response简单版

class MyResponse(): # 这里复杂一点可以继承rest_framework的Response类
    def __init__(self): # 定义一个初始化方法,该方法有默认属性status和msg(任何由该类产生的对象都有这两个属性)
        self.status=100
        self.msg = '成功'
    
    @property # 将这个方法伪装成属性
    def get_dict(self):
        return self.__dict__ # 返回一个字典

当前题目:序列化组件
网页链接:http://myzitong.com/article/dsogcsp.html