02-序列化组件的使用及接口设计-中
一.serializers.Serializer使用实例
1.通过序列化组件进行接口设计
1.1设计协定
GET 127.0.0.1:8000/books/ # 获取所有数据,返回值: [{}, {}] GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} POST 127.0.0.1:8000/books/ # 新增一条数据,返回值:{} PUT 127.0.0.1:8000/books/{id} # 修改数据,返回值:{} DELETE 127.0.0.1:8000/books/{id} # 删除数据,返回空
1.2创建models.py,数据库表创建
from django.db import models # Create your models here. 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 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 Book(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) # 外键字段 publish = models.ForeignKey(to="Publish", related_name="book", related_query_name="book_query", on_delete=models.CASCADE) # 多对多字段 authors = models.ManyToManyField(to="Author")
1.3创建urls.py
from django.urls import re_path from serializer import views urlpatterns = [ re_path(r'books/$', views.BookView.as_view()), ]
1.4创建序列化类app_serializers.py
from rest_framework import serializers class BookSerializer(serializers.Serializer): # nid = serializers.CharField(max_length=32) title = serializers.CharField(max_length=128) price = serializers.DecimalField(max_digits=5, decimal_places=2) # 外键字段, 显示__str__方法的返回值 publish = serializers.CharField(max_length=32, source="publish.city") # authors = serializers.CharField(max_length=32) # book_obj.authors.all() # 多对多字段需要自己手动获取数据,SerializerMethodField() authors_list = serializers.SerializerMethodField() 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, book_obj): return book_obj
1.5在views中使用序列化类views.py
class BookView(APIView): def get(self, request): # 第三步,获取queryset origin_data = Book.objects.all() # 第四步,开始序列化 serialized_data = BookSerializer(origin_data, many=True) return Response(serialized_data.data) 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) class BookFilterView(APIView): def get(self, request, nid): book_obj = Book.objects.get(pk=nid) serialized_data = BookSerializer(book_obj, many=False) return Response(serialized_data.data) def put(self, request, nid): book_obj = Book.objects.get(pk=nid) verified_data = BookSerializer(data=request.data, instance=book_obj) if verified_data.is_valid(): verified_data.save() return Response(verified_data.data) else: return Response(verified_data.errors) def delete(self, request, nid): book_obj = Book.objects.get(pk=nid).delete() return Response()
二.ModelSerializer
通常,你会希望序列化器紧密的映射到Django模型定义上。
ModelSerializer 类提供了一个快捷方式,可以自动创建具有与模型字段对应的字段的 Serializer
ModelSerializer 类继承于 Serializer 类,在父类上实现了以下的功能:
- 它将根据模型自动生成一组字段。
- 它将自动为序列化器生成验证器,例如 unique_together 验证器。
- 它包含默认简单实现的
.create()和.update()方法。
1.声明ModelSerializer
from rest_framework import serializers from app01.models import Book class BookSerialize(serializers.ModelSerializer): class Meta: model = Book fields = ('id', 'title', 'price', 'authors', 'publish', 'authors_list', 'publish_name', 'publish_city' ) # 附加关键字参数 extra_kwargs = { 'publish': {'write_only': True}, 'authors': {'write_only': True} } # 只读字段 read_only_fields = ('publish_name', 'publish_city') # 显式定义字段 publish_name = serializers.CharField(max_length=32, source='publish.name') publish_city = serializers.CharField(max_length=32, source='publish.city') # 多对多字段需要定义get_<field_name>方法处理数据 authors_list = serializers.SerializerMethodField() def get_authors_list(self, book_obj): authors = [author.name for author in book_obj.authors.all()] return authors
2.指定只读字段
您可能希望将多个字段指定为只读。您可以使用快捷的 Meta 选项 read_only_fields,而不是使用 read_only=True 属性显式的添加每个字段。
该选项应该是字段名称的列表或元组,并声明如下:
class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account fields = ('id', 'account_name', 'users', 'created') read_only_fields = ('account_name',)
模型中已经设置 editable=False 的字段和默认就被设置为只读的 AutoField 字段都不需要添加到 read_only_fields 选项中。
3.附加关键字参数
还有一个快捷方式允许您使用 extra_kwargs 选项在字段上指定任意附加关键字参数。与 read_only_fields 的情况一样,这意味着不需要在序列化器中显式声明该字段。
class CreateUserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('email', 'username', 'password') extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): user = User( email=validated_data['email'], username=validated_data['username'] ) user.set_password(validated_data['password']) user.save() return user
三.BaseSerializer
BaseSerialAlgisher 类,可以用来方便地支持可选的序列化和反序列化样式。
该类实现与 Serializer 类相同的基本 API:
.data—— 返回传出的基元表示。.is_valid()—— 反序列化并验证传入的数据。.validated_data—— 返回经过验证的传入数据。.errors—— 返回在验证期间的任何错误。.save()—— 将验证的数据保存到对象实例中。
可以重写四种方法,这取决于你希望序列化器类支持的功能:
.to_representation()—— 重写它以支持序列化,用于读取操作。.to_internal_value()—— 重写它以支持反序列化,以用于写入操作。.create()和.update()—— 重写其中一个或两个以支持保存实例。
因为此类提供了与 Serializer 类相同的接口,所以您可以像使用常规的 Serializer 或 ModelSerializer 一样使用现有的通用的基于类的视图。
在执行此操作时您将注意到的唯一区别是 BaseSerializer 类不会在可浏览的 API 中生成 HTML 表单。这是因为它们返回的数据不包括允许每个字段被渲染成合适的 HTML 输入的所有字段信息。
四.序列化器字段
浙公网安备 33010602011771号