序列化组件的使用及接口设计
-
请求接口设计get请求(restapi规范)
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} # 删除一条数据, 返回值: 空对象
-
创建model.py
-
python manage.py makemigrations
-
python manage.py migrate
-
urls.py
-
views.py
-
开始使用序列化
-
导入模块 from rest_framework import serializers
-
建立一个序列化类
class BookSerializer(serializers.Serializer): 字段可以自定义
-
获取queryset
origin_data = Book.objects.all()
-
开始序列化
serialized_data = BookSerializer(origin_data, many=True )
-
序列化后的数据, 返回给客户端
return Response(serialized_data.data)
-
-
案例GET请求
-
创建模型类
from django.db import models from datetime import datetime # from django.contrib.auth.models import AbstractUser class AuthorInfo(models.Model): name = models.CharField(max_length=32, verbose_name="作者名称") age = models.IntegerField(verbose_name="作者年龄") class Meta: db_table = "db_author_info" verbose_name = "作者信息" verbose_name_plural = verbose_name def __str__(self): return self.name class PublishInfo(models.Model): name = models.CharField(max_length=32, verbose_name="出版社名称") city = models.CharField(max_length=32, verbose_name="出版社所在城市") email = models.EmailField(verbose_name="出版社邮箱") class Meta: db_table = "db_publish_info" verbose_name = "出版社信息" verbose_name_plural = verbose_name def __str__(self): return self.name class BookInfo(models.Model): title = models.CharField(max_length=32, verbose_name="书名") publishDate = models.DateField(default=datetime.now, verbose_name="出版日期") # max_digits小数位加整数位多少长度 decimal_places小数位长度为2 price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="图书价格") # on_delete # CASCADE:这就是默认的选项,级联删除,你无需显性指定它。 # PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误。 # SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True,定义该字段的时候,允许为空。 # SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。 # SET(): 自定义一个值,该值当然只能是对应的实体了 publish = models.ForeignKey(PublishInfo, related_name="book", related_query_name="book_query", on_delete=models.CASCADE, verbose_name="出版社") # ManyToManyField多对多 authors = models.ManyToManyField(AuthorInfo, verbose_name="图书作者") class Meta: db_table = "db_book_info" verbose_name = "图书信息" verbose_name_plural = verbose_name def __str__(self): return self.title
-
创建urls.py
from django.urls import re_path from .views import BookView urlpatterns = [ # restapi风格定制路由 re_path(r"^books/$", BookView.as_view()), ]
-
创建views.py
-
导入模块
# 第一步: 导入模块 from rest_framework import serializers
-
建立序列化类
# 第二步: 创建序列化类, 字段类型不一定要跟model的字段一致 class BookSerializer(serializers.Serializer): title = serializers.CharField(max_length=128) publishDate = serializers.DateField(default=datetime.now) price = serializers.DecimalField(max_digits=5, decimal_places=2) # 序列化没有外键(ForeignKey)和多对多(ManyToManyField) # 显示出来的是id值, 意义不大可以不写 # 外键字段 publish = serializers.CharField() # 外键字段显示__str__方法的返回值, 但是你写了source那么source指定的值覆盖掉__str__的值 # (注意source指定的值必须是模型类里面的) # read_only=True 读的时候有它, 写的时候不需要它 publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name") publish_city = serializers.CharField(max_length=32, read_only=True, source="publish.city") # author = serializers.CharField(max_length=32) # 多对多字段需要自己手动获取数据, SerializerMethodField(), 他就会自动去找一个(get_固定格式)get_当前字段(authors) # SerializerMethodField()默认是自读字段, 写的时候是不会检查的, 它源码里写了read_only=True authors = serializers.SerializerMethodField() # 方法名必须是get_ 加上字段上面的多对多字段的名 # 固定传一个当前表的对象 def get_authors(self, book_obj): author_list = [] # book_obj.authors.all() 获取所有author对象 for author in book_obj.authors.all(): author_list.append(author.name) # 返回的值就是authors的值 return author_list
-
获取queryset/开始序列化/序列化后的数据, 返回给客户端
from rest_framework.views import APIView # Response返回序列化对象 from rest_framework.response import Response from .models import BookInfo, PublishInfo, AuthorInfo from .app_serializers import BookSerializer class BookView(APIView): def get(self, request): # 第三步: 获取queryset origin_data = BookInfo.objects.all() # 第四步: 开始序列化 # 当序列化多条数据时 要加上many=True serialized_data = BookSerializer(origin_data, many=True) # 返回序列化对象 # 记住序列化的值在data属性里 # 所以这里用serialized_data.data取序列化的值 return Response(serialized_data.data)
-
postman效果图
-
浏览器效果图
-
序列化组件接口设计post请求
-
通过序列化组件进行
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} # 删除一条数据, 返回值: 空对象
-
创建model.py
- python manage.py makemigrations
- python manage.py migrate
-
urls.py
-
views.py
-
开始使用序列化
-
导入模块 from rest_framework import serializers
-
建立一个序列化类
class BookSerializer(serializers.Serializer): 字段可以自定义
-
获取客户端请求数据
-
开始序列化
verified_data = BookSerializer(data=client_data, many=False)
-
写入数据库
book = verified_data.save() -
序列化后的数据, 返回给客户端
return Response(serialized_data.data)
-
-
-
案列POST请求
-
创建模型类
from django.db import models from datetime import datetime # from django.contrib.auth.models import AbstractUser class AuthorInfo(models.Model): name = models.CharField(max_length=32, verbose_name="作者名称") age = models.IntegerField(verbose_name="作者年龄") class Meta: db_table = "db_author_info" verbose_name = "作者信息" verbose_name_plural = verbose_name def __str__(self): return self.name class PublishInfo(models.Model): name = models.CharField(max_length=32, verbose_name="出版社名称") city = models.CharField(max_length=32, verbose_name="出版社所在城市") email = models.EmailField(verbose_name="出版社邮箱") class Meta: db_table = "db_publish_info" verbose_name = "出版社信息" verbose_name_plural = verbose_name def __str__(self): return self.name class BookInfo(models.Model): title = models.CharField(max_length=32, verbose_name="书名") publishDate = models.DateField(default=datetime.now, verbose_name="出版日期") # max_digits小数位加整数位多少长度 decimal_places小数位长度为2 price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="图书价格") # on_delete # CASCADE:这就是默认的选项,级联删除,你无需显性指定它。 # PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误。 # SET_NULL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True,定义该字段的时候,允许为空。 # SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。 # SET(): 自定义一个值,该值当然只能是对应的实体了 publish = models.ForeignKey(PublishInfo, related_name="book", related_query_name="book_query", on_delete=models.CASCADE, verbose_name="出版社") # ManyToManyField多对多 authors = models.ManyToManyField(AuthorInfo, verbose_name="图书作者") class Meta: db_table = "db_book_info" verbose_name = "图书信息" verbose_name_plural = verbose_name def __str__(self): return self.title
-
创建urls.py
from django.urls import re_path from .views import BookView urlpatterns = [ # restapi风格定制路由 re_path(r"^books/$", BookView.as_view()), ]
-
创建views.py
-
导入模块
# 第一步: 导入模块 from rest_framework import serializers
-
建立序列化类, 并且要自定义create方法
# 第二步: 创建序列化类, 字段类型不一定要跟model的字段一致 class BookSerializer(serializers.Serializer): title = serializers.CharField(max_length=128) publishDate = serializers.DateField(default=datetime.now) price = serializers.DecimalField(max_digits=5, decimal_places=2) # 序列化没有外键(ForeignKey)和多对多(ManyToManyField) # 显示出来的是id值, 意义不大可以不写 # 外键字段 publish = serializers.CharField() # 外键字段显示__str__方法的返回值, 但是你写了source那么source指定的值覆盖掉__str__的值 # (注意source指定的值必须是模型类里面的) # read_only=True 读的时候有它, 写的时候不需要它 publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name") publish_city = serializers.CharField(max_length=32, read_only=True, source="publish.city") # author = serializers.CharField(max_length=32) # 多对多字段需要自己手动获取数据, SerializerMethodField(), 他就会自动去找一个(get_固定格式)get_当前字段(authors) # SerializerMethodField()默认是自读字段, 写的时候是不会检查的, 它源码里写了read_only=True authors = serializers.SerializerMethodField() # 方法名必须是get_ 加上字段上面的多对多字段的名 # 固定传一个当前表的对象 def get_authors(self, book_obj): author_list = [] # book_obj.authors.all() 获取所有author对象 for author in book_obj.authors.all(): author_list.append(author.name) # 返回的值就是authors的值 return author_list def create(self, validated_data): # 把上面所有的字段放在validated_data里面 # {'price': Decimal('66.00'), 'publishDate': datetime.date(2019, 7, 25), 'title': 'python666', 'publish': '2'} print(validated_data) validated_data["publish_id"] = validated_data.pop("publish") # {'publishDate': datetime.date(2019, 7, 25), 'publish_id': '2', 'title': 'python666', 'price': Decimal('66.00')} print(validated_data) # **validated_data 字典解析 # 创建数据库对象并且保存在数据库中, 并把这个对象返回给book book = BookInfo.objects.create(**validated_data) return book
-
获取数据/开始序列化/序列化后的数据, 返回给客户端
from rest_framework.views import APIView # Response返回序列化对象 from rest_framework.response import Response from .models import BookInfo, PublishInfo, AuthorInfo from .app_serializers import BookSerializer class BookView(APIView): def get(self, request): # 第三步: 获取queryset origin_data = BookInfo.objects.all() # 第四步: 开始序列化 # 当序列化多条数据时 要加上many=True serialized_data = BookSerializer(origin_data, many=True) # 返回序列化对象 # 记住序列化的值在data属性里 # 所以这里用serialized_data.data取序列化的值 return Response(serialized_data.data) def post(self, request): # 接受前端发送的json数据 client_data = request.data # many默认是False, 可以省略不写 # 开始序列化 verified_data = BookSerializer(data=client_data, many=False) # 判断序列化数据的合法性 if verified_data.is_valid(): # 当执行save()他就会去找create方法, 并且接受create的返回值 book = verified_data.save() # 查询出id在request.data这个列表里的对象 authors = AuthorInfo.objects.filter(id__in=request.data["authors"]) # *authors列表解析 # book这个对象下的authors是一个列表把查询出来的authors对象添加到book.authors对象中 book.authors.add(*authors) return Response(verified_data.data) else: return Response(verified_data.errors)
-
postman效果图
-