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}}
原文地址:https://www.cnblogs.com/--kai/p/10105690.html