首页 > 其他分享 >drf之序列化组件

drf之序列化组件

时间:2023-02-01 21:46:26浏览次数:37  
标签:serializers ser drf instance 组件 序列化 data name

目录

drf之序列化组件

序列化与反序列化器

序列化器介绍和快速使用

  • 在写接口时,需要序列化和反序列化,而且反序列化的过程中要做数据校验,drf直接提供了固定的写法,只需要按照固定写法使用,就能完成上面的三个需求。
  • 提供了两个类 Serializer ModelSerializer,编写自定义的类,只需要继承drf提供的序列化类,就可以使用其中的某些方法,也能完成上面的三个需求

基于序列化器劣化和反序列化

序列化类基本使用

序列化

  1. 序列化多条

    serializer.py--BookSerializer类

    from rest_framework import serializers
    
    class BookSerializer(serializers.Serializer):
        # 序列化某些字段,这里写要序列化的字典
        name = serializers.CharField()  # serializers下大致跟models下的类是对应的
        price = serializers.CharField()
        publish = serializers.CharField()
    

    如果只是想序列化某几字段,就把不需要序列化的字段注释掉即可

    views.py--->BookView类

    class BookView(APIView):
        def get(self, request):
            # 只是为了验证之前讲过的
            print(request.method)  # GET
            print(request._request)  # <WSGIRequest: GET '/books/'>
            print(type(self.request))  # <class 'rest_framework.request.Request'>
    
            books = Book.objects.all()
            # 使用序列化类来完成---》得有个序列化类
            # instance要序列化的数据books queryset对象
            # many=True 只要是queryset对象要传many=True,如果是单个对象就不用传
            ser = BookSerializer(instance=books, many=True)
            return Response(ser.data)  # 无论是列表还是字典都可以序列化
    
  2. 序列化单条

    序列化类--默认

    from rest_framework import serializers
    
    class BookSerializer(serializers.Serializer):
        # 序列化某些字段,这里写要序列化的字典
        name = serializers.CharField()  
        price = serializers.CharField()
        publish = serializers.CharField()
    

    views.py--->BookDetailView类

    class BookDetailView(APIView):
        # def get(self, request,pk):  # 与下列方法时一样的,
        def get(self, request, *args, **kwargs):  # pk是以关键字传入的
            book = Book.objects.filter(pk=kwargs.get('pk')).first()
            # 序列化
            ser = BookSerializer(instance=book)
            return Response(ser.data)
    

    url 路由

    添加了新的路由

    urlpatterns = [
        path('books/<int:pk>/',views.BookDetailView.as_view())
    ]
    

反序列化

  1. 序列化的新增

    序列化类

    
    class BookSerializer(serializers.Serializer):
        # 序列化某些字段,这里写要序列化的字典
        name = serializers.CharField()  
        price = serializers.CharField()
        publish = serializers.CharField()
    
        # 新增一条数据
        def create(self, validated_data):
            # 保存的逻辑
            # validated_data 校验过后的数据 {name,price,publish}
            # 保存到数据库
            book = Book.objects.create(**validated_data)
            # 一定不要忘记返回新增的对象
            return book
    

    视图类

    class BookView(APIView):
        def post(self, request):
            # requset.data  # 前端提交要保存的数据-->校验数据-->存数据
            ser = BookSerializer(data=request.data)  # 把前端传入的要保存的数据,给data参数
            # 校验数据
            if ser.is_valid():
                # 保存-->需要自己写,要在序列化类BookSerializer中写-->create方法
                ser.save()  # 调用ser.save,自动触发自定义编辑create方法保存数据
                return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
            else:
                return Response({'code': 101, 'msg': ser.errors})
            
            
       注释:
            print(ser)
                """BookSerializer(data=<QueryDict: {'name': ['cc'], 'price': ['123'], 'publish': ['上海']}>):
                    name = CharField()
                    price = CharField()
                    publish = CharField()
                    """
                print(ser.data)  # {'name': 'cc', 'price': '123', 'publish': '上海'}
    
  2. 反序列化的修改

    序列化类

    class BookSerializer(serializers.Serializer):
        # 序列化某些字段,这里写要序列化的字典
        name = serializers.CharField()  
        price = serializers.CharField()
        publish = serializers.CharField()
    
        def create(self, validated_data):
            book = Book.objects.create(**validated_data)
            return book
    	
        # 修改对象
        def update(self, instance, validated_data):
            # instance 要修改的对象
            # validated_data 校验过后的数据
            instance.name = validated_data.get('name')
            instance.price = validated_data.get('price')
            instance.publish = validated_data.get('publish')
            instance.save()  # orm的单个对象,修改了单个对象的属性,只要调用对象.save,就能把修改保存到数据库
    
            return instance  # 记得把修改的对象返回
    

    视图类

    class BookDetailView(APIView):
    
        def put(self, request, pk):
            book = Book.objects.filter(pk=pk).first()
            # 反序列化保存 ---借助于序列化类
            ser = BookSerializer(data=request.data, instance=book)
            if ser.is_valid():
                ser.save()  # 由于没有重写update,所以这报错
                return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
            else:
                return Response({'code': 101, 'msg': ser.errors})
    
  3. 删除单条

    视图类

    class BookDetailView(APIView):
        def delete(self,request,pk):
            Book.objects.filter(pk=pk).delete()
            return Response({'code':100,'msg':'删除成功'})
    

基于序列化器编写5个接口(重点)

url

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/',views.BookView.as_view()),
    path('books/<int:pk>/',views.BookDetailView.as_view())
]

models.py

from django.db import models

class Book(models.Model):
    name = models.CharField(max_length=32,verbose_name='书名')
    price = models.CharField(max_length=32,verbose_name='价格')
    publish = models.CharField(max_length=32,verbose_name='出版社')

serializer.py

from rest_framework import serializers
from .models import Book
# 多条
class BookSerializer(serializers.Serializer):
    # 序列化某些字段,这里泻药序列化的字典
    name = serializers.CharField()
    price = serializers.CharField()
    publish = serializers.CharField()


    # 新增一条数据
    def create(self, validated_data):
        # 保存的逻辑
        # validated_data 校验过后的数据 {name,price,publish}
        # 保存到数据库
        book=Book.objects.create(**validated_data)
        # 一定不要忘记返回新增的对象
        return book

    # 修改数据
    def update(self, instance, validated_data):
        # instance 要修改的对象
        # validated_data 校验过后的数据
        instance.name=validated_data.get('name')
        instance.price=validated_data.get('price')
        instance.publish=validated_data.get('publish')
        instance.save()  # orm的单个对象,修改了单个对象的属性,只要调用对象.save,就能把修改保存到数据库

        return instance # 不要忘了把修改后的对象,返回

view.py

from rest_framework.views import APIView,Response
from .models import Book
from django.http import JsonResponse
from django.core.handlers.wsgi import WSGIRequest
from rest_framework.request import Request

# 序列化多条
from .serializer import BookSerializer
class BookView(APIView):
     def get(self,request):
         # 只是为了验证之前讲过的
         print(request.method)
         print(request._request)
         print(type(self.request))

         books = Book.objects.all()

         # 使用自定义的序列化类来完成
         # instance要序列化的数据books queryset对象
         # many=True 只要是queryset对象要传many=True,如果是单个对象就不用传
         ser = BookSerializer(instance=books,many=True)
         return Response(ser.data)

		# 反序列化---新增
        def post(self,request):
        # requset.data  # 前端提交要保存的数据-->校验数据-->存数据
        ser = BookSerializer(data=request.data)
        # 检验数据
        if ser.is_valid():
            # 保存-->需要自己写,要在序列化类BookSerializer中写-->create方法
            ser.save()  # 调用ser.save,自动触发自定义编辑create方法保存数据
            # print(ser)
            """BookSerializer(data=<QueryDict: {'name': ['cc'], 'price': ['123'], 'publish': ['上海']}>):
                name = CharField()
                price = CharField()
                publish = CharField()
                """
            # print(ser.data)  # {'name': 'cc', 'price': '123', 'publish': '上海'}
            print(ser.errors)
            return Response({'code':100,'msg':'新增成功','result':ser.data})
        else:
            return Response({'code':101,'msg':ser.errors})


# 序列---单条
from .serializer import BookSerializer
class BookDetailView(APIView):
     def get(self,request,*args,**kwargs):
         book = Book.objects.filter(pk=kwargs.get('pk')).first()
         # 序列化
         ser =BookSerializer(instance=book)
         return Response(ser.data)

	# 反序列化---修改数据
    def put(self,request,pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(data=request.data,instance=book)
        if ser.is_valid():
            ser.save()  # # 由于没有重写update,所以这报错
            return Response({'code':100,'msg':'修改成功','result':ser.data})
        else:
            return Response({'code':101,'msg':ser.errors})

    # 反序列化---删除数据
    def delete(self,request,pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'code':100,'msg':'删除成功'})
    

反序列化的校验

序列化类反序列化的数据校验功能类比forms组件

  • 局部钩子
  • 全局钩子

代码实现

class BookSerializer(serializers.Serializer):
    name = serializers.CharField()  
    price = serializers.CharField()
    publish = serializers.CharField()
    
    # 新增一条数据
    def create(self, validated_data):
        book = Book.objects.create(**validated_data)
        return book
    
    # 修改一条数据
    def update(self, instance, validated_data):
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish = validated_data.get('publish')
        instance.save()
        return instance  # 保存
    
    # 反序列化校验的局部钩子,名字不能以h开头
    def validate_name(self,name):
        # 校验name是否合法
        if name.startswith('h'):
            # 校验不通过,抛异常
            raise ValidationError('不能以h开头')
        else:
            return name
     
   # 全局钩子
	def validate(self,attrs):
        # 校验过后的数据,书名和出版社的名字不能一致
        if attrs.get('name')==attrs.get('publish'):
            raise ValidationError('书名和出版社的名字不能一致')
        else:
            return attrs
	

练习题

  1. 基于序列化器编写5个接口 Publish
  2. 使用局部钩子和全局钩子校验 5个接口
    3.原生的request 没有data 属性 实现一个原生的 request.data 拿出无论什么编码格式提交的数
    FBV--->写个装饰条

标签:serializers,ser,drf,instance,组件,序列化,data,name
From: https://www.cnblogs.com/zhanglanhua/p/17084212.html

相关文章