ModelSerializer序列化器实战
上篇ModelSerializer序列化器做了一个小demo,演示了如何操作单表进行序列化和反序列化来实现五个API的使用,多表大差不差????,这里对四个表写五个API接口
单表操作
单表操作序列化类demo:
序列化器类
# ModelSerializer和表模型有绑定关系 class BookSerializer1(serializers.ModelSerializer): class Meta: model = Book # 指定和哪个表有关系 # 所有字段 # fields = '__all__' # 这里注意id字段是从表模型映射过来的,auto自增的,不传也可以 # 自定制的字段不传必须注册,在列表中 fields = ['id', 'title', 'price', 'price_info'] # 指定字段 extra_kwargs = { 'title': {'write_only': True, 'max_length': 8, 'min_length': 3} } # 指定序列化的字段:两种写法:在序列化类中写;models中写 price_info = serializers.SerializerMethodField() def get_price_info(self, obj): return "价格是:" + str(obj.price) ''' 注意:自定制字段如果和表模型获取到的字段是同名,那么自定制返回给前端的字段值就被自定制覆盖了,比如: title = serializers.SerializerMethodField() def get_title(self, obj): return "书名是:" + str(obj.title) ''' # 局部和全局钩子,跟之前一样,但是要注意写在Meta外
视图类
from rest_framework.views import APIView from .models import Book from rest_framework.response import Response from app01.serializer import BookSerializer1 class BookView1(APIView): def get(self, request): # 从数据库查数据,做序列化 book_list = Book.objects.all() # 实例化类,传入初始化的参数,instance和many ''' instance:要序列化的对象 qs,单个对象 many:如果是qs对象,many=True,如果是单个对象many=False ''' ser = BookSerializer1(instance=book_list, many=True) # ser.data使用模型类的对象得到序列化后的字典 return Response(ser.data) def post(self,request): # 反序列化,保存到数据库使用data参数 deser = BookSerializer1(data=request.data) # 校验数据 if deser.is_valid(): # 保存需要重写create方法,不然不知道存到哪个表 deser.save() return Response(deser.data) return Response({'code':101,'msg':'校验不通过','errors':deser.errors}) # 处理修改再写一个视图类,防止get冲突 class BookDetailView1(APIView): def get(self,request,pk): book = Book.objects.filter(pk=pk).first() ser = BookSerializer1(instance=book) # 这里设置了主键值,单条记录many不需要写 return Response(ser.data) def delete(self,request,pk): res = Book.objects.filter(pk=pk).delete() print(res) # (1, {'app01.Book': 1}) # res是影响的行数 if res[0]>0: return Response({'code': 100, 'msg': '删除成功'}) else: return Response({'code': 103, 'msg': '要删除的数据不存在'}) # 反序列化修改 def put(self,request,pk): # 修改处理单条数据用过pk确定求改哪条数据 book = Book.objects.filter(pk=pk).first() # 序列化器类实例化需要传入instance,data才表示修改 ser = BookSerializer1(instance=book,data=request.data) if ser.is_valid(): # 重写update方法才能存入 ser.save() return Response(ser.data) return Response({'code':101,'msg':'校验未通过','error':ser.errors})
路由
path('books1/', views.BookView1.as_view()), path('books1/<int:pk>', views.BookDetailView1.as_view()),
模型
from django.db import models class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5,decimal_places=2) authors = models.CharField(max_length=32)
多表操作
models.py
from django.db import models # build four model tables class Book(models.Model): name = models.CharField(max_length=32) price = models.DecimalField(decimal_places=2, max_digits=5) publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE) authors = models.ManyToManyField(to='Author') def __str__(self): return self.name # 自定制字段 @property def publish_detail(self): return {'name': self.publish.name, 'addr': self.publish.city} @property def author_list(self): l = [] print(self.authors.all()) # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]> for author in self.authors.all(): print(author.author_detail) # AuthorDetail object (1) l.append({'name': author.name, 'age': author.age, 'addr': author.author_detail.addr}) return l class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE) def __str__(self): return self.name @property def authordetail_info(self): return {'phone':self.author_detail.telephone,'addr':self.author_detail.addr} class AuthorDetail(models.Model): telephone = models.BigIntegerField() addr = models.CharField(max_length=64) class Publish(models.Model): name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField()
serializer.py
from app01 import models from rest_framework import serializers # 书序列化器 class BookSerializer(serializers.ModelSerializer): class Meta: # 指定和哪个表有关系 model = models.Book # fields = '__all__' fields = ['id','name','price','publish','authors','publish_detail','author_list'] # 将关联表的信息全部取出来,不推荐使用 # depth = 1 extra_kwargs = { 'publish':{'write_only':True}, 'authors':{'write_only':True} } # 作者序列化器 class AuthorSerializer(serializers.ModelSerializer): class Meta: # 指定和哪个表有关系 model = models.Author # fields = '__all__' fields = ['id', 'name', 'age', 'author_detail', 'authordetail_info'] extra_kwargs = { 'author_detail': {'write_only': True}, } # 作者详情序列化器 class AuthorDetailSerializer(serializers.ModelSerializer): class Meta: # 指定和哪个表有关系 model = models.AuthorDetail fields = '__all__' # 出版社序列化器 class PublishSerializer(serializers.ModelSerializer): class Meta: # 指定和哪个表有关系 model = models.Publish fields = '__all__'
views.py
from rest_framework.response import Response from rest_framework.views import APIView from app01 import models from app01 import serializer # 书视图类 class BookView(APIView): def get(self, requets): # 序列化 book_list = models.Book.objects.all() # 序列化多条数据many=True ser = serializer.BookSerializer(instance=book_list, many=True) return Response(ser.data) def post(self, request): # 获取反序列化数据 ser = serializer.BookSerializer(data=request.data) if ser.is_valid(): # 校验通过存入数据库,不需要重写create方法了 ser.save() return Response({'code': 100, 'msg': '新增成功', 'data': ser.data}) # 校验失败 return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors}) class BookViewDetail(APIView): def get(self, request, pk): book = models.Book.objects.filter(pk=pk).first() ser = serializer.BookSerializer(instance=book) return Response(ser.data) def put(self, request, pk): book = models.Book.objects.filter(pk=pk).first() # 修改,instance和data都要传 ser = serializer.BookSerializer(instance=book, data=request.data) if ser.is_valid(): # 校验通过修改,不需要重写update ser.save() return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data}) # 校验不通过 return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors}) def delete(self, request, pk): models.Book.objects.filter(pk=pk).delete() return Response({'code': 100, 'msg': '删除成功'}) # 作者视图类 class AuthorView(APIView): def get(self, requets): # 序列化 author_list = models.Author.objects.all() # 序列化多条数据many=True ser = serializer.AuthorSerializer(instance=author_list, many=True) return Response(ser.data) def post(self, request): # 获取反序列化数据 ser = serializer.AuthorSerializer(data=request.data) if ser.is_valid(): # 校验通过存入数据库,不需要重写create方法了 ser.save() return Response({'code': 100, 'msg': '新增成功', 'data': ser.data}) # 校验失败 return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors}) class AuthorViewDetail(APIView): def get(self, request, pk): book = models.Author.objects.filter(pk=pk).first() ser = serializer.AuthorSerializer(instance=book) return Response(ser.data) def put(self, request, pk): book = models.Author.objects.filter(pk=pk).first() # 修改,instance和data都要传 ser = serializer.AuthorSerializer(instance=book, data=request.data) if ser.is_valid(): # 校验通过修改,不需要重写update ser.save() return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data}) # 校验不通过 return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors}) def delete(self, request, pk): models.Author.objects.filter(pk=pk).delete() return Response({'code': 100, 'msg': '删除成功'}) # 作者详情视图类 class AuthorDetailView(APIView): def get(self, requets): # 序列化 author_list = models.AuthorDetail.objects.all() # 序列化多条数据many=True ser = serializer.AuthorDetailSerializer(instance=author_list, many=True) return Response(ser.data) def post(self, request): # 获取反序列化数据 ser = serializer.AuthorDetailSerializer(data=request.data) if ser.is_valid(): # 校验通过存入数据库,不需要重写create方法了 ser.save() return Response({'code': 100, 'msg': '新增成功', 'data': ser.data}) # 校验失败 return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors}) class OneAuthorViewDetail(APIView): def get(self, request, pk): book = models.AuthorDetail.objects.filter(pk=pk).first() ser = serializer.AuthorDetailSerializer(instance=book) return Response(ser.data) def put(self, request, pk): book = models.AuthorDetail.objects.filter(pk=pk).first() # 修改,instance和data都要传 ser = serializer.AuthorDetailSerializer(instance=book, data=request.data) if ser.is_valid(): # 校验通过修改,不需要重写update ser.save() return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data}) # 校验不通过 return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors}) def delete(self, request, pk): models.AuthorDetail.objects.filter(pk=pk).delete() return Response({'code': 100, 'msg': '删除成功'}) # 出版社视图类 class PublishView(APIView): def get(self, requets): # 序列化 author_list = models.Publish.objects.all() # 序列化多条数据many=True ser = serializer.PublishSerializer(instance=author_list, many=True) return Response(ser.data) def post(self, request): # 获取反序列化数据 ser = serializer.PublishSerializer(data=request.data) if ser.is_valid(): # 校验通过存入数据库,不需要重写create方法了 ser.save() return Response({'code': 100, 'msg': '新增成功', 'data': ser.data}) # 校验失败 return Response({'code': 101, 'msg': '校验未通过', 'error': ser.errors}) class PublishViewDetail(APIView): def get(self, request, pk): book = models.Publish.objects.filter(pk=pk).first() ser = serializer.PublishSerializer(instance=book) return Response(ser.data) def put(self, request, pk): book = models.Publish.objects.filter(pk=pk).first() # 修改,instance和data都要传 ser = serializer.PublishSerializer(instance=book, data=request.data) if ser.is_valid(): # 校验通过修改,不需要重写update ser.save() return Response({'code:': 100, 'msg': '修改成功', 'data': ser.data}) # 校验不通过 return Response({'code:': 102, 'msg': '校验未通过,修改失败', 'error': ser.errors}) def delete(self, request, pk): models.Publish.objects.filter(pk=pk).delete() return Response({'code': 100, 'msg': '删除成功'})
urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), # 书 path('books/', views.BookView.as_view()), path('books/<int:pk>', views.BookViewDetail.as_view()), # 作者 path('authors/', views.AuthorView.as_view()), path('authors/<int:pk>', views.AuthorViewDetail.as_view()), # 作者详情 path('authorsdetail/', views.AuthorDetailView.as_view()), path('authorsdetail/<int:pk>', views.OneAuthorViewDetail.as_view()), # 出版社 path('publish/', views.PublishView.as_view()), path('publishdetail/<int:pk>', views.PublishViewDetail.as_view()), ]
优化操作
我们知道作者表和作者详情表的表关系是一对一的关系,那么新增数据的时候,就得先新增作者详情表,再增作者表的数据,但是在实际生活中,用户不知道表关系这码事,为了体验更好,可以重写create方法,同时存两个表的内容,给用户的感觉就是操作了一张表
'''优化作者表的序列化器''' # 作者序列化器 class AuthorSerializer(serializers.ModelSerializer): class Meta: # 指定和哪个表有关系 model = models.Author # fields = '__all__' fields = ['id', 'name', 'age', 'telephone', 'addr','authordetail_info'] # 重写字段telephone和addr telephone = serializers.CharField(write_only=True) addr = serializers.CharField(write_only=True,max_length=8,required=False) # 重写create,操作两个表 def create(self, validated_data): # 先存作者详情 authordetail = models.AuthorDetail.objects.create(telephone=validated_data.get('telephone'),addr=validated_data.get('addr')) # 存作者表 author = models.Author.objects.create(author_detail=authordetail,name=validated_data.get('name'),age=validated_data.get('age')) # 这样只返回author对象就行,直接存了两个表,返回反序列化的对象 return author
Postman自行测试,我测了测都能用,有问题望指正~
注意
如果实际项目中不需要操作数据库可以使用APIView,如果操作数据库那么推荐使用GenericAPIView
热门文章
- 动物疫苗一般在哪里*** 动物疫苗一般在哪里***的
- 动物医院社会实践报告怎么写的(动物医院社会实践总结)
- 「1月29日」最高速度22M/S,2025年Shadowrocket/SSR/Clash/V2ray每天更新免费订阅地址分享
- 「1月19日」最高速度20.7M/S,2025年V2ray/Shadowrocket/SSR/Clash每天更新免费订阅地址分享
- 动物医院诊室如何管理 动物医院诊室如何管理好
- 「2月14日」最高速度21.2M/S,2025年Shadowrocket/V2ray/SSR/Clash每天更新免费订阅地址分享
- 同城免费领养宠物的软件有哪些(同城领养宠物的app)
- 猫粮十大品牌有哪些牌子(猫粮10大品牌排行榜)
- 「2月15日」最高速度21.4M/S,2025年SSR/Shadowrocket/V2ray/Clash每天更新免费订阅地址分享
- SpringCloud Sleuth分布式请求链路追踪