• serializer的使用及DRF的解析器和序列化组件


    原生serializer的使用

    from django.core.serializers import serialize
    
    class StudentView(APIView):
    
        def get(self, request):
           
            origin_students = Student.objects.all()
            serialized_students = serialize("json", origin_students)
    
            return HttpResponse(serialized_students)
    

    DRF解析器组件

    使用:

    #1. 引入模块
    
    from rest_framework.views import APIView
    
    #2. 继承APIView
    
    class LoginView(APIView):
        parser_classes = [FormParser]
    
        def get(self, request):
            return render(request, 'parserver/login.html')
    
    # .3. 直接request.data就可以获取json数据
    
        def post(self, request):
            # request是被drf封装的新对象,基于django的request
            # request.data是一个property,用于对数据进行校验
            # request.data最后会找到self.parser_classes中的解析器
            # 来实现对数据进行解析
            
            print(request.data)  # {'username': 'alex', 'password': 123}
    
            return JsonResponse({"status_code": 200, "code": "OK"})
    

     解释器组件源码流程 

    序列化组件

    定义几个model

    from django.db import models
    
    # Create your models here.
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
        def __str__(self):
            return self.name
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        publishDate = models.DateField()
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)
        authors = models.ManyToManyField(to="Author")
    
        def __str__(self):
            return self.title
    

      

    设计url,请求接口

    GET接口

    url:

    from django.urls import re_path
    
    from serializers import views
    
    urlpatterns = [
        re_path(r'books/$', views.BookView.as_view())
    ]
    

     新建一个名为app_serializers.py的模块,将所有的序列化的使用集中在这个模块里面,对程序进行解耦:

    from rest_framework import serializers
    
    from .models import Book
    #1.定义序列化类 class BookSeriazlizer(seriazlizers.Serializer):
      #2.定义需要返回的字段(字段类型可以与model中的类型不一致,参数也可以调整),
      字段名称必须与model中的一致
      title = serializers.CharField(max_length=128)  
      publish_date = serializers.DateTimeField()
        price = serializers.DecimalField(max_digits=5, decimal_places=2)
        publish = serializers.CharField(max_length=32)
        authors = serializers.CharField(max_length=32)
    

     视图类,使用序列化组件 

    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from .models import Book
    from .app_serializer import BookSerializer
    
    
    class BookView(APIView):
        
        def get(self,request):
    #3. GET接口逻辑中,获取QuerySet origin_books = Book.objects.all()
    #4.开始序列化 ,many默认为False,若返回的数据是个多个对象集合,需改为True serialized_books = BookSerializer(origin_books,many=True) return Response(serialized_books.data)

    下面是通过POSTMAN请求该接口后的返回的测试数据,除ManyToManyField字段不是想要的外,其他的都没有任何问题: 

    [
        {
            "title": "Python入门",
            "publishDate": null,
            "price": "119.00",
            "publish": "浙江大学出版社",
            "authors": "serializers.Author.None"
        },
        {
            "title": "Python进阶",
            "publishDate": null,
            "price": "128.00",
            "publish": "清华大学出版社",
            "authors": "serializers.Author.None"
        }
    ]
    

      

    若当字段定义为多个参数时,比如authors.all,取出来的结果将是一个querset,对前端来书,这样的数据不太友好,稍微改进下

    class BookSerializer(serializers.Serializer):
        title = serializers.CharField(max_length=32)
        price = serializers.DecimalField(max_digits=5, decimal_places=2)
        publishDate = serializers.DateField()
        publish = serializers.CharField()
        publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name')
        publish_email = serializers.CharField(max_length=32, read_only=True, source='publish.email')
        # authors = serializers.CharField(max_length=32, source='authors.all')
        authors_list = serializers.SerializerMethodField()
    
        def get_authors_list(self, authors_obj):
            authors = list()
            for author in authors_obj.authors.all():
                authors.append(author.name)
    
            return authors
    
    
    
    
    # 注:get_必须与字段名称一致,否则会报错
    

     

    POST接口设计

    def post(self, request):
            verified_data = BookSerializer(data=request.data)
    
            if verified_data.is_valid():
                book = verified_data.save()
                # 可写字段通过序列化添加成功之后需要手动添加只读字段
                authors = Author.objects.filter(nid__in=request.data['authors'])
                book.authors.add(*authors)
    
                return Response(verified_data.data)
            else:
                return Response(verified_data.errors)
    

      多对多字段同样需要自己手动来获取

    def get_authors_list(self, book_obj):
            author_list = list()
    
            for author in book_obj.authors.all():
                author_list.append(author.name)
    
            return author_list
    
        def create(self, validated_data):
            # {'title': 'Python666', 'price': Decimal('66.00'), 'publish': '2'}
            validated_data['publish_id'] = validated_data.pop('publish')
            book = Book.objects.create(**validated_data)
    
            return book
    
        def update(self, instance, validated_data):
            # 更新数据会调用该方法
            instance.title = validated_data.get('title', instance.title)
            instance.publishDate = validated_data.get('publishDate', instance.publishDate)
            instance.price = validated_data.get('price', instance.price)
            instance.publish_id = validated_data.get('publish', instance.publish.nid)
    
            instance.save()
    
            return instance
    

      

    感觉还是有点麻烦,若字段很多,写序列化也是一种负担,更加简单的方式如下:

    # 继承ModelSerializer
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
    
            fields = ('title',
                      'price',
                      'publish',
                      'authors',
                      'author_list',
                      'publish_name',
                      'publish_city'
                      )
            extra_kwargs = {
                'publish': {'write_only': True},
                'authors': {'write_only': True}
            }
    
        publish_name = serializers.CharField(max_length=32, read_only=True, source='publish.name')
        publish_city = serializers.CharField(max_length=32, read_only=True, source='publish.city')
    
        author_list = serializers.SerializerMethodField()
    
        def get_author_list(self, book_obj):
            # 拿到queryset开始循环 [{}, {}, {}, {}]
            authors = list()
    
            for author in book_obj.authors.all():
                authors.append(author.name)
    
            return authors
    

      详细步骤:

    • 继承ModelSerializer:不再继承Serializer
    • 添加extra_kwargs类变量:extra_kwargs = {‘publish’: {‘write_only’: True}}
  • 相关阅读:
    WIN平台下ASE使用资源文件创建ASE服务
    C#高级编程笔记(三)
    C#高级编程笔记(四)
    高质量的HTML+CSS。
    C#高级编程笔记(二)
    编写高质量代码(JavaScript篇)
    C#高级编程笔记(一)
    开始博客+生活+学习
    巴中故里
    纱丽
  • 原文地址:https://www.cnblogs.com/--kai/p/10105690.html
Copyright © 2020-2023  润新知