Django 原生 serializer (序列化)

  1. 导入模块  from django.core.serializers import serialize 
  2. 获取 queryset 
  3. 对 queryset 进行序列化
  4. 将序列化之后的数据,返回给客户端

首先,设计url, 先只定义GET和POST接口

from django.urls import path

from DrfOne import views

urlpatterns = [
    path('books/', views.BookView.as_view()),
]

再定义几个models

DRF Django REST framework 之 序列化(三)-LMLPHPDRF Django REST framework 之 序列化(三)-LMLPHP
 1 from django.db import models
 2
 3
 4 class Publish(models.Model):
 5     nid = models.AutoField(primary_key=True)
 6     name = models.CharField("出版社名", max_length=32)
 7     address = models.CharField("出版社位置", max_length=32)
 8     email = models.EmailField("邮箱")
 9
10     def __str__(self):
11         return self.name
12
13
14 class Author(models.Model):
15     nid = models.AutoField(primary_key=True)
16     name = models.CharField("姓名", max_length=31)
17     age = models.IntegerField("年龄")
18
19     def __str__(self):
20         return self.name
21
22
23 class Book(models.Model):
24     nid = models.AutoField(primary_key=True)
25     title = models.CharField("书名", max_length=32)
26     price = models.DecimalField("价格", max_digits=5, decimal_places=2)
27     publish = models.ForeignKey(to="Publish", on_delete=models.CASCADE)
28     authors = models.ManyToManyField(to="Author")
29
30     def __str__(self):
31         return self.title
models.py

使用

from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
# 1.导入模块
from django.core.serializers import serialize


class CourseView(APIView):
    def get(self, request):
        # 2.获取queryset    
        course_obj = models.Course.objects.all()
        # 3.序列化
        serialized_data = serialize("json", course_obj)
        print(serialized_data)
        # 4.将序列化之后的数据返回
        return HttpResponse(serialized_data)

序列化组件serializer的使用

Serializer

GET接口设计(获取所有数据)

  1. 导入模块
  2. 建立一个序列化类
  3. 获取 queryset 
  4. 开始序列化
  5. 获取序列化后的数据,返回给客户端
from rest_framework.views import APIView
# 1.导入模块
from rest_framework import serializers
# drf重新封装之后的Response基于TemplateResponse类型,
# 可以将未处理的内容通过内容协商来决定返回给客户端的正确内容形式
from rest_framework.response import Response

from DrfOne import models


# 2.创建一个序列化类,字段名和字段类型不一定要跟models的字段一样
class BookSerializer(serializers.Serializer):
    # id一般情况不用写
    # nid = serializers.CharField(max_length=32)
    title = serializers.CharField(max_length=32)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    # 外键字段,显示__str__方法的返回值
    publish = serializers.CharField()

    # 多对多字段, 执行get_字段名 方法,手动获取数据
    author_list = serializers.SerializerMethodField()

    def get_author_list(self, book_obj):
        # 第二个参数随意
        author_list = list()
        for author in book_obj.authors.all():
            author_list.append(author.name)
        return author_list


class BookView1(APIView):
    def get(self, request):
        # 3.获取queryset
        book_objs = models.Book.objects.all()
        # 4.通过序列化类进行序列化
        serialized_obj = BookSerializer(book_objs, many=True)
        # print(serialized_obj)

        # 5.获取序列化之后的数据,返回给客户端
        return Response(serialized_obj.data)

POST接口设计

  1. 导入模块
  2. 建立一个序列化类
  3. 获取客户端请求数据
  4. 开始序列化
  5. 写入数据库
  6. 将插入的对象返回给客户端

请注意,因为多对多关系字段是我们自定义的,而且必须这样定义,返回的数据才有意义,而用户插入数据的时候,serializers.Serializer没有实现create,我们必须手动插入数据,就像这样:

# 1.导入模块
from rest_framework import serializers
from rest_framework.views import APIView
# drf重新封装之后的Response基于TemplateResponse类型,
# 可以将未处理的内容通过内容协商来决定返回给客户端的正确内容形式
from rest_framework.response import Response

from DrfOne import models


# 2.创建一个序列化类,字段名和字段类型不一定要跟models的字段一样
class BookSerializer(serializers.Serializer):
    # id一般情况不用写
    # nid = serializers.CharField(max_length=32)
    title = serializers.CharField(max_length=32)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    # 外键字段,显示__str__方法的返回值
    publish = serializers.CharField()
    # 仅读字段read_only=True,source是该字段显示出版社地址
    publish_address = serializers.CharField(max_length=32, read_only=True, source="publish.address")
    publish_email = serializers.CharField(max_length=32, read_only=True, source="publish.email")

    # 多对多字段, 执行get_字段名 方法,手动获取数据
    author_list = serializers.SerializerMethodField()

    def get_author_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):
        # 创建时调用
        validated_data['publish_id'] = validated_data.pop('publish')
        book = models.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


class BookView(APIView):
    def get(self, request):
        pass

    def post(self, request):
        # 3.获取客户端的数据
        client_data = request.data
        # 4.序列化,默认many=False单条数据
        verified_data = BookSerializer(data=client_data)
        # 对数据进行验证
        if verified_data.is_valid():
            # 5.写入数据库
            book = verified_data.save()
            authors = models.Author.objects.filter(nid__in=request.data["authors"])
            book.authors.add(*authors)
            # 6.将插入的对象数据返回
            return Response(verified_data.data)
        # 验证失败返回错误信息
        return Response(verified_data.errors)

从上面可以看出:

  1.  serializers.Serializer 无法插入数据,只能自己实现。
  2. 字段太多,不能自动序列化

这样就会非常复杂化程序,如果我希望序列化类自动插入数据呢?

这也就有了 ModelSerializer 

ModelSerializer

 ModelSerializer  类似于form组件里的 ModelForm 

from rest_framework import serializers
from rest_framework.views import APIView


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"

        extra_kwargs = {
            # 仅写
            "publish": {'write_only': True},
            "authors": {'write_only': True},
        }

    publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name")
    publish_address = serializers.CharField(max_length=32, read_only=True, source="publish.address")
    author_name = serializers.SerializerMethodField()

    def get_author_name(self, book_obj):
        author_list = list()
        for author in book_obj.authors.all():
            # 注意列表添加字段,author.name而不是author
            author_list.append(author.name)
        return author_list

这样看起来简单多了!

get(单条数据)、put(改)、delete(删) 接口设计

设计url

from django.urls import path, re_path

from DrfOne import views

urlpatterns = [
    path('books/', views.BookView.as_view()),
    re_path("books/(\d+)/", views.BookFilterView.as_view()),
]

视图设计

class BookFilterView(APIView):
    def get(self, request, nid):
        # 获取queryset
        book_obj = models.Book.objects.get(pk=nid)
        # 序列化
        serialized_data = BookSerializer(book_obj)
        # 返回数据
        return Response(serialized_data.data)

    def put(self, request, nid):
        # 获取queryset
        book_obj = models.Book.objects.get(pk=nid)
        # 序列化, 根据instance是确认是否是更新, many默认为False可以不写
        verified_data = BookSerializer(data=request.data, instance=book_obj, many=False)
        if verified_data.is_valid():
            verified_data.save()
            # 返回数据
            return Response(verified_data.data)
        return Response(verified_data.errors)

    def delete(self, request, nid):
        models.Book.objects.get(pk=nid).delete()

        return Response("")

~>.<~

12-12 02:52