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 不能连用