drf--视图家族
drf 视图家族
前期准备
总路由 urls.py
from django.contib import admin
from django.views import serve
from django.conf import settings
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')),
url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
]
基表:utils/models.py
from django.db import models
class BaseModel(models.Model):
is_delete = models.BooleanField(default=False)
create_time = models.DateTimeField(auto_now_add=True, null=True)
class Meta:
# 抽象表, 不会完成数据库迁移
abstract = True
模型层 api/models.py
from django.db import models
from utils.models import BaseModel
class Book(BaseModel):
name = models.CharField(max_length=64)
price = models.DecimalField(max_digits=6, decimal_places=2)
img = models.ImageField(upload_to='icon', default='icon/default.png')
publish = models.ForeignKey(to='Publish',
null=True,
related_name='books',
db_constraint=False,
on_delete=models.DO_NOTHING
)
authors = models.ManyToManyField(to='Author',
related_name='authors',
db_constraint=False
@property
def publish_info(self):
return {'name': self.publish.name, 'address': self.publish.address}
@property
def author_info(self):
author_list = []
for author in self.authors.all():
detail = AuthorDetail.objects.filter(author_id=self.author.id)
author_list.append({
'name': author.name,
'age': author.age,
'mobile': '未知' if not detail else author.detail.mobile
})
return author_list
class Meta:
db_table = "books"
verbose_name = '书籍'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class Author(BaseModel):
name = models.CharField(max_length=64)
age = models.IntegerField()
@property
def mobile(self):
return self.detail.mobile
class Meta:
db_table = 'author'
verbose_name = '作者'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class AuthorDetail(BaseModel):
mobile = models.CharField(max_length=11)
author = models.OneToOneField(to='Author',
null=True,
related_name='detail',
db_constraint=False,
on_delete=models.CASCADE
)
class Meta:
db_table = 'detail'
verbose_name = '作者详情'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.author.name}的详情"
class Publish(BaseModel):
name = models.CharField(max_length=64)
address = models.CharField(max_length=128)
class Meta:
db_table = 'publish'
verbose_name = '出版社'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
序列化器 api/serializers.py
from rest_framework import serializers
from . import models
class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
for ind, obj in enumerate(instance):
for attr, value in validated_data[ind].items():
if hasattr(obj, attr):
set(obj, attr, value)
obj.save()
return instance
class BookV2ModelSerializer(serializers.ModelSerializer):
re_name = serializers.CharField(
min_length=3,
required=True,
write_only=True, # 只参与反序列化
error_messages={
'min_length': '太短了',
'required': '不能为空'
}
)
class Meta:
model = models.Book
fields = ('name', 're_name', 'price', 'img', 'publish', 'publish_info', 'authors', 'authors_info')
list_serializer_class = BookListSerializer
extra_kwargs = {
'name':{
'min_length': 3,
'error_messages': {
'min_length': '太短了',
'required': '不能为空'
}
},
# 有默认值的字段会默认required为False,在反序列化中如果不传值不会进行校验,但是如果传值就会进行校验
'publish':{
'required': True,
'write_only': True,
'error_messages':{
'required': '不能为空'
}
},
'authors':{
'required': True,
'write_only': True,
'error_messages':{
'required': '不能为空'
}
},
}
# 自定义校验规则
# 局部钩子
def validate_name(self, value):
if 'sb' in value:
raise serializers.ValidationError('书名包含敏感词汇')
return value
# 全局钩子
def validate(self, attr):
name = attr.get('name')
re_name = attr.get('re_name')
publish = attr.get('publish')
if name != re_name:
raise serializers.ValidationError(
{'re_name': '两次书名不一致'}
)
# 通过逻辑控制联合唯一
if models.Book.objects.filter(name=name, publish=publish):
raise serializers.ValidationError(
{'book': '书籍已存在'}
)
return attr
基本视图(views)
主要就是通过视图类APIView,里面的逻辑都需要自己去实现,需要自己写接口
子路由 api/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^books/$', views.BookAPIView.as_view()),
url(r'^books/(?P<pk>.*)/$', views.BookAPIView.as_view()),
]
视图层 api/views.py
from rest_framework import views
from . import models, serializers
from utils.response import APIResponse
class BookAPIView(views.APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
# 单取
if pk:
book_obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
if not pk:
return APIResponse(1, 'pk有误')
book_ser = serializers.BookV2ModelSerializer(book_obj)
return APIResponse(0, 'ok', results=book_ser.data)
# 群取
book_obj_list = models.Book.objects.filter(is_delete=False).all()
if not book_obj_list:
return APIResponse(1, '没有数据')
book_ser = serializers.BookV2ModelSerializer(book_obj_list, many=True)
return APIResponse(0, 'ok', results=book_ser.data)
# 增加
def post(self, request, *args, **kwargs):
# 把单增也转换为群增
request_data = request.data
if isinstance(request_data, dict):
data = [request_data, ]
elif isinstance(request, list):
data = request_data
else:
return APIView(1, '数据格式有误')
book_ser = serializers.BookV2ModelSerializer(data=data, many=True)
if book_ser.is_valid():
book_obj_list = book_ser.save()
results = serializers.BookV2ModelSerializer(book_obj_list, many=True).data
return APIResponse(0, 'ok', results=results)
else:
return APIResponse(1, '添加失败', results=book_ser.errors)
视图工具类(mixins)
RetrieveModelMixin
:retrieve方法实现了获取一个对象ListModelMixin
:list方法实现了获取多个对象CreateModelMixin
:create方法实现了增加一个对象UpdateModelMixin
:update方法实现了单整体更新,partial_udate实现了单局部更新DestroyModelMixin
:destory方法实现了单独删除
一般结合generics工具视图使用
工具视图(generics)
GenericAPIView
GenericAPIView
,是generics家族的基类,主要帮我们把qureyset
和serializer_class
封装成了属性,提供了以下三种方法:
get_qureyset():
获取多个对象get_object():获取一个对象
get_serializer(*args, **kwargs):
获取序列化后的对象
GenericAPIView
的子类们
继承了mixins
中多个功能类和GenericAPIView
基类
类名 | 实现接口 |
---|---|
CreateAPIView |
单增(post) |
ListAPIView |
多取(get) |
RetrieveAPIView |
单取(get) |
DestroyAPIView |
单删(delete) |
UpdateAPIView |
单局部(patch)及整体(put)修改 |
ListCreateAPIView |
多取(get)和多增(post) |
RetrieveUpdateAPIView |
单取(get),单局部(patch)及整体(put)修改 |
RetrieveDestroyAPIView |
单取(get)和单删(delete) |
RetrieveUpdateDestroyAPIView |
单取(get),单局部(patch)及整体(put)修改和单删(delete) |
子路由 api/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
# generics
url(r'^v1/books/$', views.BookGenericAPIView.as_view()),
url(r'^v1/books/(?P<pk>.*)/$', views.BookGenericAPIView.as_view()),
# mixins + generics
url(r'^v2/books/$', views.BookMixinsGenericAPIView.as_view()),
url(r'^v2/books/(?P<pk>.*)/$', views.BookMixinsGenericAPIView.as_view()),
# 系统整合mixins、generics
url(r'^v3/books/$', views.BookRetrieveUpdateAPIView.as_view()),
url(r'^v3/books/(?P<pk>.*)/$', views.BookRetrieveUpdateAPIView.as_view()),
]
视图层 api/views.py
from rest_framework import generics, mixins
from . import models, serializers
from utils.response import APIResponse
# v1 generics - 视图基类
class BookGenericAPIView(generics.GenericAPIView):
queryset = models.Book.objects.filter(is_delete=False).order_by('-id')
serializer_class = serializers.BookModelSerializer
def get(self, request, *args, **kwargs):
if 'pk' in kwargs:
book_obj = self.get_object()
book_ser = self.get_serializer(book_obj)
return APIResponse(0, 'ok', results=book_ser.data)
book_query = self.get_queryset()
book_ser = self.get_serializer(book_query, many=True)
return APIResponse(0, 'ok', results=book_ser.data)
def post(self, request, *args, **kwargs):
book_ser = self.get_serializer(data=request.data)
book_ser.is_valid(raise_exception=True)
book_obj = book_ser.save()
return APIResponse(0, 'ok', results=self.get_serializer(book_obj).data)
# v2 mixins工具集 + generics视图基类
class BookMixinsGenericAPIView(mixins.RetrieveModelMixin, mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
queryset = models.Book.objects.filter(is_delete=False).order_by('-id')
serializer_class = serializers.BookModelSerializer
def get(self, request, *args, **kwargs):
if 'pk' in kwargs:
response = self.retrieve(request, *args, **kwargs)
else:
response = self.list(request, *args, **kwargs)
return APIResponse(0, 'ok', results=response.data)
def post(self, request, *args, **kwargs):
response = self.create(request, *args, **kwargs)
return APIResponse(0, 'ok', results=response.data)
# v3 视图基类子类 - 工具视图类
class BookRetrieveUpdateAPIView(generics.RetrieveUpdateAPIView):
queryset = models.Book.objects.filter(is_delete=False).order_by('-id')
serializer_class = serializers.BookModelSerializer
视图集(viewsets)
ViewSetMixin
:视图集工具,重写了as_view方法, 完成了请求方式到视图类中的方法的映射
例如:.as_view({'get': 'retrieve', 'delete': 'remove_obj'})
, 表示当请求方式为get的时候,则会调用retrieve函数,当请求方式为delete的时候,则会调用remove_obj函数
GenericViewSet
:与模型类有关的接口视图集 - 可以从mixins那继承功能,也可以自定义功能
ViewSet
:与模型类无关或不是标准模型类接口 - 一般都是自定义功能
子路由 api/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^v4/books/$', views.BookGenericViewSet.as_view({
'get': 'list',
'post': 'create'
})),
url(r'^v4/books/(?P<pk>.*)/$', views.BookGenericViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'remove_book'
})),
]
视图层 api/views.py
from rest_framework import mixins, viewsets
from . import models, serializers
from utils.response import APIResponse
class BookGenericViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):
queryset = models.Book.objects.filter(is_delete=False).order_by('-id')
serializer_class = serializers.BookModelSerializer
def remove_book(self, request, *args, **kwargs):
pk = kwargs.get('pk')
try:
book_obj = models.Book.objects.get(is_delete=False, pk=pk)
book_obj.is_delete = True
book_obj.save()
return APIResponse(0, '删除成功')
except:
return APIResponse(1, '删除失败')
drf--视图家族的更多相关文章
- DRF 视图家族及路由层补充
目录 视图家族 一.views视图类 1.APIView类 2.GenericAPIView类(generics中) 二.mixins类:视图辅助工具 1.RetrieveModelMixin 2.L ...
- drf框架 - 视图家族 | GenericAPIView | mixins | generics | viewsets
视图家族 view:视图 generics:工具视图 mixins:视图工具集 viewsets:视图集 学习曲线: APIView => GenericAPIView => mixins ...
- drf序列化组件之视图家族
一.视图家族的分类 1.导入分类 from rest_framewok import views, generics, mixins, viewsets views:视图类 两大视图类:APIVi ...
- drf序列化高级、自定义只读只写、序列化覆盖字段、二次封装Response、数据库查询优化(断关联)、十大接口、视图家族
目录 自定义只读 自定义只写 序列化覆盖字段 二次封装Response 数据库关系分析 断外键关联关系 ORM操作外键关系 ORM四种关联关系 基表 系列化类其他配置(了解) 十大接口 BaseSer ...
- drf二次封装response-APIViews视图家族-视图工具集-工具视图-路由组件
视图类传递参数给序列化类 (1).在视图类中实例化 序列化对象时,可以设置context内容. (2).在序列化类中的局部钩子.全局钩子.create.update方法中,都可以用self.conte ...
- 视图家族 & 路由组件
目录 视图家族 & 路由组件 视图集与路由组件 基于 GenericAPIView 的十大接口 基于 generics 包下工具视图类的六大基础接口 视图集 路由组件:必须配合视图集使用 自定 ...
- 使用DRF视图集时自定义action方法
在我们用DRF视图集完成了查找全部部门,创建一个新的部门,查找一个部门,修改一个部门,删除一个部门的功能后,views.py的代码是这样子的: class DepartmentViewSet(Mode ...
- 【DRF视图】
目录 开始使用内置视图 请结合[DRF序列化]此文献中的数据文件及序列化文件来阅读如下代码. DRF视图为我们提供了非常简便的方法--内置了增删改查等一系列的操作. 我们只需在url中指定对应的方法, ...
- day73_10_18视图家族与序列化的传参。
一.序列化传参 在视图类中实例化序列对象时,还有一个参数为context,这个参数是存放字典,将所有从前端传来的数据传输到序列化中,比如需要在序列化中校验当前用户. 传入的request参数也是一个对 ...
- DRF视图-请求与响应
DRF视图 drf的代码简写除了在数据序列化体现以外,在视图中也是可以的.它在django原有的django.views.View类基础上,drf内部封装了许多子类以便我们使用. Django RES ...
随机推荐
- linux之shell脚本学习(一)
#!/bin/bash echo 'hello' your_name='longxiong' echo $your_name echo ${your_name} for i in `ls /opt`; ...
- java、python及jmeter操作redis(接口自动化必备)
redis是nosql数据库之一,其存储结构简单,提供高性能服务,所以在架构中是很常用的. 在做接口自动化测试过程中,有时也会涉及到redis,比如:发送短信验证码,我们做接口自动化测试,如何模拟发送 ...
- 30-ESP8266 SDK开发基础入门篇--SPI
这节只是做记录, 整个的教程呢,重新整理下 教程有点乱,需要再细分一下 这节只是做一下我使用其SPI的记录 还是老样子,看人家LUA源码里面怎么使用的 注意哈,对于8266 SDK的学习我还是建议大家 ...
- 洛谷 p3870 开关 线段树模板
这两天学了很长时间于是做了一道水题 我就用了模板,就连任何优化都没有 就AC了,复杂度也很爆炸10个点1500多毫秒 这个题就是把lazy[]改成记录下修改的次数,每次修改的时候mod 2,因为反过来 ...
- Unix/Linux小计
1. centos查看cpu信息 cat /proc/cpuinfo processor有几个就是有几个cpu,每一列是每个cpu的信息 每个processor中的cores是当前cpu中有几个核心. ...
- Gamma展示
团队成员简介 团队成员 角色 个人博客地址 刘峻辰 后端开发 刘峻辰 焦云鹏 后端开发 焦云鹏 赵智源 测试&服务器部署 赵智源 肖萌威 前端开发 肖萌威 杨亦鑫 前端开发 杨亦鑫 戴荣 UI ...
- 小米win10+kali 双系统
1.下载kali linux 系统镜像,用windisk32imager 制作启动盘,制作好后千万不要格式化u盘,其他的启动盘制作工具不好用,无法加载系统镜像 2.将u盘插入电脑,重启,电脑重启时按 ...
- | C语言I作业04
| C语言I作业004 标签: 18软件 李煦亮 问题 答案 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://www.cnblogs.com/pengchen511/p/ ...
- windowsServer-------- 系统中调出文件扩展名
Windows Server是微软发布的一系列服务器操作系统的品牌名. 各个品牌的发布日期 Windows Server 2003 (2003年4月) Windows Server 2003 R2(2 ...
- idea(2018.3.5)破解
第一步:下载idea,https://www.jetbrains.com/idea/download/#section=windows,双击进行安装 第二步:下载破解的jar包:链接:https:// ...