基于APIView&ModelSerializer写接口

​ 引言,首先路由写法还是不变、视图层的视图类写法不变,在序列化类要改变写法、慢慢的靠近序列化器组件;而且需要创建关联表,因为现实生活当中不可能仅仅建单表,会使用大量的多表关联的表数据。好吧!咱们上干货把,首先准备一下路由吧,毕竟就两条代码而且配好就逻辑写完可以马上测试接口了。本篇文章重点介绍了序列化定制字段的多种方法,也演示了序列化重要字段DictField()、ListField()的用法和反序列化重要参数read_only=True和write_only=True

一、首先准备前提工作

1.模型代码

from django.db import models

class Book(models.Model):
name = models.CharField(verbose_name='书名', max_length=32)
price = models.CharField(verbose_name='价格', max_length=32) # 外键 书跟出版社是一对多
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
# 外键 书跟作者是多对多
authors = models.ManyToManyField(to='Author') class Publish(models.Model):
name = models.CharField(verbose_name='出版社名称', max_length=32)
address = models.CharField(verbose_name='出版社地址', max_length=32) class Author(models.Model):
name = models.CharField(verbose_name='作者姓名', max_length=32)
phone = models.CharField(verbose_name='电话号码', max_length=11)

录入数据的顺序不能乱来,因为有外键关系、那么小编在这里详细的列出录入数据的过程

先在Author表录入两条

再在publish表录入两条

然后在book表录入两条

最后在关联表添加数据

2.路由代码

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.BookDetailView.as_view()),
]

3.视图代码

from django.shortcuts import render
from rest_framework.views import APIView
from .models import Book
from .serializer import BookSerializer
from rest_framework.response import Response class BookView(APIView):
def get(self, request): # 查询所有
# 查询所有数据
books = Book.objects.all()
# 序列化数据
ser = BookSerializer(instance=books, many=True)
return Response(ser.data) def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors}) class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(data=request.data, instance=book)
if ser.is_valid():
ser.save()
return Response({'code':100, 'msg':'修改成功'})
else:
return Response({'code':101, 'msg':ser.errors}) def get(self, request, pk):
book = Book.objects.filter(pk=pk)
ser = BookSerializer(instance=book)
return Response(ser.data) def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response('删除成功')

二、继承Serializer序列化定制字段的三种方法

1.通过source关键词定制

# 用source关键字定制字段的代码

from rest_framework import serializers

class BookSerializer(serializers.Serializer):
real_name = serializers.CharField(source='name')
real_price = serializers.CharField(source='price')
publish = serializers.CharField(source='publish.name')
authors = serializers.CharField()





第一个解决方案是在模型表中写下面的方法



第二种解决方案在序列化类处理看下面代码框

2.SerializerMethodField定制

该方法能够序列化定制所有的任何的字段先想好定制成什么样子,之后新字段名跟get_后面即可,记得定制一个就一定要配合一个get_方法,可以自定义返回格式,就说明个性化能力强。


"""关键字段SerializerMethodField定制""" class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField() publish_detail = serializers.SerializerMethodField() def get_publish_detail(self, obj):
return {'name':obj.publish.name, 'address':obj.publish.address} author_list = serializers.SerializerMethodField() def get_author_list(self, obj):
list =[]
for author in obj.authors.all():
list.append({'name':author.name, 'phone':author.phone})
return list

3.在模型表中写方法来定制

这个方法其实算不上方法,因为逻辑是一样的,只不过把方法写到模型表里面,而序列化类里面只需要写新定制字段,所以相当于做了所谓的解耦合吧,但是我感觉完全没这个必要,毕竟要序列化,那么属性和方法统一写到一个位置比较省心。当然这是我的个人想法,仅供参考。

# 序列化类代码
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
publish_detail = serializers.DictField()
author_list = serializers.ListField()
# 模型表写定制方法代码
def publish_detail(self):
return {'name': self.publish.name, 'address': self.publish.address} def author_list(self):
list = []
for author in self.authors.all():
list.append({'name': author.name, 'phone': author.phone})
return list

三、继承Serializer反序列化

当然定制字段的方法也要写,不管在序列化类里写还是模型表里写,但凡涉及到定制字段就要写定制方法,因为涉及到反序列化所以要重写create方法和update方法,而且也要写数据校验,毕竟不能前端传什么就录入,一定要有校验机制的

class BookSerializer(serializers.Serializer):
# 如果一个字段既用来序列化又用来反序列化就不用写参数read_only或write_only
name = serializers.CharField(max_length=8, error_messages={'max_length':'太长了'})
price = serializers.CharField() # 只用来序列化 写参数read_only=True
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True) # 只用来反序列化 写参数write_only=True
publish = serializers.CharField(write_only=True)
author = serializers.ListField(write_only=True) # 反序列化要重写create方法和update方法
def create(self, validated_data):
# 新增一本书
book = Book.objects.create(name=validated_data.get('name'),
price=validated_data.get('price'),
publish_id=validated_data.get('publish'))
# 关联作者
book.authors.add(*validated_data.get('author'))
# 返回book
return book def update(self, instance, validated_data):
# 序列出数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish_id = validated_data.get('publish')
# 先清空数据在add
authors = validated_data.get('author')
print(validated_data)
instance.authors.clear()
instance.authors.add(*authors)
# 修改完保存
instance.save()
# 返回数据
return instance # 修改要重写update
def update(self, instance, validated_data):
# validated_data 校验过后的数据,{name:红楼梦,price:19,publish:1,authors:[1,2]}
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish_id = validated_data.get('publish') # 先清空,再add
authors = validated_data.get('authors')
instance.authors.clear()
instance.authors.add((*authors) instance.save() return instance

四、用ModelSerializer进行序列化与反序列化

"""ModelSerializer的用法"""

class BookSerializer(serializers.ModelSerializer):
class Meta:
# 跟book表关联
model = Book
# fields = ['写需要序列化的字段名',[]···]
# 如果fields = '__all__'这样写就表明序列化所有字段
fields = '__all__'
# extra_kwargs = {'字段名': {'约束条件': 约束参数},是反序列化字段
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'authors_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True}
} def validate_name(self, name):
if name.startswith('sb'):
raise ValidationError('书名不能以sb开头')
else:
return name

展示效果如下

基于APIView&ModelSerializer写接口的更多相关文章

  1. 【转】基于laravel制作APP接口(API)

    这篇文章主要介绍了基于laravel制作APP接口(API)的相关资料,需要的朋友可以参考下 前期准备 前言,为什么做以及要做个啥本人姓小名白,不折不扣编程届小白一名,但是自从大一那会儿接触到编程这件 ...

  2. 基于SSM之Mybatis接口实现增删改查(CRUD)功能

    国庆已过,要安心的学习了. SSM框架以前做过基本的了解,相比于ssh它更为优秀. 现基于JAVA应用程序用Mybatis接口简单的实现CRUD功能: 基本结构: (PS:其实这个就是用的Mapper ...

  3. node+pm2+express+mysql+sequelize来搭建网站和写接口

    前面的话:在这里已经提到了安装node的方法,node是自带npm的.我在技术中会用es6去编写,然后下面会分别介绍node.pm2.express.mysql.sequelize.有少部分是摘抄大佬 ...

  4. 基于PCIe的高速接口设计

    基于PCIe的高速接口设计 由 judyzhong 于 星期四, 03/03/2016 - 13:49 发表 作者:李晓宁,姚远程,秦明伟 2016年微型机与应用第1期 摘要:PCIe总线是第三代I/ ...

  5. 基于Python的WEB接口开发与自动化测试 pdf(内含书签)

    基于Python的WEB接口开发与自动化测试 目录 目 录O V目 录章 Python 学习必知 ................................................... ...

  6. atitit.基于http json api 接口设计 最佳实践 总结o7

    atitit.基于http  json  api 接口设计 最佳实践 总结o7 1. 需求:::服务器and android 端接口通讯 2 2. 接口开发的要点 2 2.1. 普通参数 meth,p ...

  7. java为移动端写接口

    java作为一门后端语言,其厉害之处在于web,大家比较熟知的各种网络应用,java都能做,那么在这个移动优先的时代,如何继续发挥java的强大呢.通常是让java作为一个app的服务端,为app客户 ...

  8. 用yii2给app写接口(下)

    上一节里我们讲了如何用Yii2搭建一个能够给App提供数据的API后台应用程序.那么今天我们就来探讨下授权认证和通过API接口向服务器提交数据以及如何控制API接口返回那些数据,不能返回那些数据. 授 ...

  9. [MyBatis]DAO层只写接口,不用写实现类

    团队开发一个项目,由老大架了一个框架,遇到了DAO层不用写接口了,我也是用了2次才记住这个事的,因为自己一直都是习惯于写DAO层的实现类,所以,习惯性的还是写了个实现类.于是遇到错误了. 找不到那个方 ...

  10. 放弃antd table,基于React手写一个虚拟滚动的表格

    缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...

随机推荐

  1. 将自己的组件打包发布到npm

    在项目中有些组件在各个项目中都会调用,那么将组件发布到npm ,用到的项目去下载,这样会省去一些不必要的麻烦. 将组件发布到npm 中的步骤 做个记录 1.项目的创建,我这里使用 vue init w ...

  2. java反序列化cc_link_one2

    CC-LINK-one_second 前言 这条链子其实是上一条链子的另一种走法,在调用危险函数哪里是没有什么变化的 整体链子 还是尾部没有变化嘛还是InvokerTransformer的transf ...

  3. 常用Python库整理

    记录工作和学习中遇到和使用过的Python库. Target 四个Level 整理 Collect 学习 Learn 练习 Practice 掌握 Master 1. Python原生和功能增强 1. ...

  4. I Love Big Numbers !(高精度)

    题目链接 题意: 多组数据输入也就是C++中的: int n; while (cin >> n) { 代码块 } 对于每个数据输出其阶乘的各位上的数字之和.大眼一看,没有思路,那就百度把. ...

  5. nginx的域名重写和转发案例

    对url进行重写 location = /tongyong_OTA_1.0.3.bin { rewrite ^(.*)$ http://36.133.87.223/lecode-server/leco ...

  6. JS图片放大镜功能实现

    JS图片放大镜功能实现 技术关键点 1.左侧和上侧距离,在一个水平位置和垂直位置中有我们可以挪动的区域,就是原图片区域,鼠标挪动位置是一个块状位置,他的左侧和上侧距离浏览器上侧和左侧分别有一个长度,我 ...

  7. Datawhale组队学习_Task03:详读西瓜书+南瓜书第4章

    第4章 决策树 4.1 基本流程 #输入:训练集D={${(x_1,y_1),(x_2,y_2),...,(x_m,y_m)}$}; #属性集A=${{a_1,a_2,...,a_d}}$. #过程: ...

  8. SLM6500电磁干扰认证设计PCB

    SLM6500 是一款面向5V交充适配器的2A离子电池充电器.它是采用1.5MHz固定频率的步降压型转换器,利用芯片内部的功率晶体管电池进行涓流.恒流和恒压充电.充电电流可用外部电阻编程设定,持续充电 ...

  9. 一个简单的工具开发:从学生端更新程序部署工具说起,浅谈qt中自定义控件制作和调用、TCP协议下文件的收发 、以及可执行文件的打包

    一个简单的工具开发:从学生端更新程序部署工具说起,浅谈qt中ui的使用和TCP协议下文件的收发.以及可执行文件的打包 写在前面,Qt Designer是一个非常操蛋的页面编辑器,它非常的...怎么说呢 ...

  10. Jenkins&&gitlab

    DevOps 强调整个组织的合作以及交付和基础设施变更的自动化 gitlab下载: 下载地址: https://docs.gitlab.com/ee/install/requirements.html ...