DRF的序列化器serializers

  DRF的序列化器的主要作用是将不同请求的数据“序列化”为指定格式的数据结构返回给接口的调用者。

  视图函数中使用DRF中的Response返回数据 —— 返回的数据按照规范一定是一个能被序列化的“字典”  —— 如果失败,返回的字典中要有状态码及错误的信息。

  序列化器serializers的使用可以参照forms的Form组件与ModelForm组件的使用,它们的使用方式十分的相似。

  自定义的序列化器的类可以继承Serializer,也可以继承ModelSerializer。

  使用Serializer进行序列化的方法可以参见这个例子基于DRF的图书增删改查练习

  下面介绍一下ModelSerializer的使用!

ModelSerializer的使用

有Model如下

from django.db import models


class Publisher(models.Model):
    name = models.CharField(max_length=32)


class Author(models.Model):
    name = models.CharField(max_length=32)


class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(decimal_places=2,max_digits=5)
    pub_date = models.DateField(auto_now=True)
    category = models.IntegerField(choices=((1,'娱乐'),(2,'科技'),(3,'财经')),default=1)
    pub = models.ForeignKey(to=Publisher,on_delete=models.CASCADE)
    authors = models.ManyToManyField(Author)

路由如下

主路由做了分发:

from django.contrib import admin
from django.urls import path,re_path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('^book/', include(('book.urls','book'))),
]

分路由如下:

from django.urls import path,re_path

from book import views

urlpatterns = [
    re_path(r'^books/$',views.BookView.as_view(),name='books'),
    re_path(r'^book/(\d+)/$',views.BookDetail.as_view(),name='book_detail'),
]

视图函数如下:—— 注意视图中是用Response返回的~

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response

from book import models
from book.my_serializers import BookSerializers


class BookView(APIView):

    def get(self,request):
        queryset = models.Book.objects.all()
        # 多个对象,需要加many=True
        ser_obj = BookSerializers(queryset,many=True)
        return Response(ser_obj.data)

    def post(self,request):
        ser_obj = BookSerializers(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        else:
            return Response(ser_obj.errors)


class BookDetail(APIView):
    # 获取一个对象
    def get(self,request,pk):
        queryset = models.Book.objects.filter(pk=pk).first()
        ser_obj = BookSerializers(queryset)
        return Response(ser_obj.data)

    def put(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()
        # 需要加参数~partial=True表示可以局部更新
        ser_obj = BookSerializers(instance=book_obj,data=request.data,partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        else:
            return Response(ser_obj.errors)

    def delete(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()
        if book_obj:
            book_obj.delete()
            return Response({'status':200,'msg':'删除成功'})
        else:
            return Response({'status':404,'msg':'删除的书籍不存在!'})

自定义的序列化器如下(使用ModelSerializer):

# -*- coding:utf-8 -*-
from rest_framework import serializers

from book import models


# 出版社的序列化器
class PubSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Publisher
        # 只显示name
        fields = ['name']

# 作者的序列化器
class AuthorSerializers(serializers.ModelSerializer):

    class Meta:
        model = models.Author
        # 显示所有字段
        fields = '__all__'


# 书籍的序列化器
# 利用ModelSerializer
class BookSerializers(serializers.ModelSerializer):

    category_info = serializers.SerializerMethodField()
    pub_info = serializers.SerializerMethodField()
    authors_info = serializers.SerializerMethodField()

    # choices字段的数据
    def get_category_info(self,book_obj):
        return book_obj.get_category_display()

    # 外键字段的数据 —— 用另外一个序列化器
    def get_pub_info(self,book_obj):
        pub_obj = book_obj.pub
        ser_obj = PubSerializers(pub_obj)
        return ser_obj.data

    # 多对多关系的数据 —— 用另外一个序列化器
    def get_authors_info(self,book_obj):
        # 记得加all()方法
        authors_obj = book_obj.authors.all()
        ser_obj = AuthorSerializers(authors_obj,many=True)
        return ser_obj.data

    class Meta:
        model = models.Book
        fields = '__all__'
        # exclute = [] # 注意在序列化器中两个不能一起用!

        # 额外的配置 —— 以下字段只在写入数据的时候使用
        extra_kwargs = {
            'category':{'write_only':True},
            'pub':{'write_only':True},
            'authors':{'write_only':True},
        }

 

posted on 2019-08-15 15:37  江湖乄夜雨  阅读(524)  评论(0编辑  收藏  举报