Django-restframework之序列化组件

Django-restframework之序列化组件

前言

这篇博客介绍 restframework的序列化组件,这个组件可以说是 rest framework 的核心组件,不仅提供了功能强大的序列化功能,还提供了数据验证的功能(与 django 的 forms 组件类似)。

普通版本使用

urls 配置

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    # url(r'^books/', views.Books.as_view()),
    url(r'^book/(?P<id>\d+)/', views.Book.as_view()),
]

models 配置

from django.db import models


# Create your models here.
# book_obj.author.set(*[])

class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.IntegerField()
    publish = models.ForeignKey(to='Publish', to_field='nid')
    pub_date = models.DateTimeField(auto_now_add=True)
    author = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book', 'author'))

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '图书表'
        verbose_name_plural = verbose_name


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    email = models.EmailField()

    class Meta:
        verbose_name = '出版社表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=32, null=True)

    class Meta:
        verbose_name = '作者表'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class Book2Author(models.Model):
    nid = models.AutoField(primary_key=True)
    book = models.ForeignKey(to='Book', to_field='nid')
    author = models.ForeignKey(to='Author', to_field='nid')

    class Meta:
        verbose_name = '图书作者表'
        verbose_name_plural = verbose_name

myser 配置(序列化组件)

from rest_framework import serializers

class BookSerib(serializers.Serializer):
    nid = serializers.CharField()
    title = serializers.CharField(source='name')
    pri = serializers.CharField(source='price')
    pub_date = serializers.CharField()
    author_dic = serializers.SerializerMethodField()

    def get_author_dic(self, obj):
        authors = obj.author.all()
        print('authors', authors)
        for author in authors:

            return {'name': author.name, 'phone': author.phone}

views 配置

from rest_framework.response import Response
from rest_framework.views import APIView

from app01 import models
from app01.myser import BookSerib

# class Author(View):
#     pass


class Books(APIView):

    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    # @staticmethod
    def get(self, request, *args, **kwargs):

        response = {'status': 100, 'msg': None}

        book_list = models.Book.objects.all()
        book_ser = BookSerib(book_list, many=True)
        print('book_ser.data', book_ser.data)
        response['books'] = book_ser.data
        print('response', response)
        return Response(response)

    def post(self, request, *args, **kwargs):
        response = {'status': 100, 'msg': None}
        bookname = request.data.get('name')
        price = request.data.get('price')
        publish = request.data.get('publish')
        authors = request.data.get('author')
        # print(authors)

        if bookname and price and publish and authors:
            pub_obj = models.Publish.objects.filter(name=publish).first()
            book = models.Book.objects.filter(name=bookname).first()
            if book:
                response['msg'] = '图书已存在'

            else:

                if pub_obj:
                    authstr_list = [author.strip() for author in authors.split(',')]
                    # print('authstr_list', authstr_list)
                    auth_list = []
                    for author in authstr_list:
                        auth_obj = models.Author.objects.filter(name=author).first()
                        if auth_obj:
                            auth_list.append(auth_obj)
                    if auth_list:
                        # print('request.data', request.data)
                        ins_dic = dict(request.data)
                        # print(type(ins_dic))
                        ins_dic.pop('author')
                        # print('ins_dic', ins_dic)
                        book_obj = models.Book.objects.create(name=bookname, price=price, publish=pub_obj)

                        book_data = BookSerib(book_obj, many=False)

                        # print('book_obj', book_obj)
                        # ret = book_obj.author.add(*auth_list)
                        for auth in auth_list:
                            models.Book2Author.objects.create(book=book_obj, author=auth)
                        # print('ret', ret)
                        response['msg'] = '新增图书成功'
                        response['book'] = book_data.data
                    else:
                        response['msg'] = '作者不存在'
                else:
                    response['msg'] = '出版社不存在'
        else:
            response['msg'] = '信息不完整'

        return Response(response)

进阶版本使用

主要是序列化模块里面的改动

# myser.py

class AuthorSerib(serializers.Serializer):
    name_author = serializers.CharField(source='name')
    phone_num = serializers.CharField(source='phone')

class BookSerib(serializers.Serializer):
    nid = serializers.CharField()
    title = serializers.CharField(source='name')
    pri = serializers.CharField(source='price')
    pub_date = serializers.CharField()
    author_dic = serializers.SerializerMethodField()
    # author_dic = AuthorSerib()
#
    def get_author_dic(self, obj):
        authors = obj.author.all()
        
        authors_ser = AuthorSerib(authors, many=True)
        return authors_ser.data
    
# 对于外键关联的字段,因为在 Book 表中存储的是对象,所以可以对该对象再使用序列化,新建了序列化 Author 的序列化类用来对 author 进行序列化

终极版本使用

# myser.py

class AuthorSerib(serializers.Serializer):
    name_author = serializers.CharField(source='name')
    phone_num = serializers.CharField(source='phone')

class BookSerib(serializers.ModelSerializer):
    
    class Meta:
        fields = '__all__' # 序列化 Book 表中所有字段
        fields = ['name', 'price', 'publish'] # 选择性的序列化字段
        exclude = ['pub_date'] # 列表里面的字段不序列化
        depth = 1 # 连表查询的深度,不建议使用,因为深度查询的参数不能控制
        
    publish_name = serializers.CharField(source='publish.name') # 因为在 Book 表中外键关联了 publish 表,所以可以通过点语法取值
    authors = serializers.SerializerMethodField()
    
    def get_authors(self, obj): # 在那个类中调用该序列化类,比如需要获取 Book 信息,使用 BookSerib 类来序列化数据,那么 obj 就是 Book 类。
        author_list = obj.author.all()
        author_ser = AuthorSerib(author_list, many=True)
        return author_ser.data 

注意:fields 和 exclude 不能连用

posted @ 2019-02-22 09:41  rsuxwvilc  阅读(91)  评论(0)    收藏  举报