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)

  1. RetrieveModelMixin:retrieve方法实现了获取一个对象
  2. ListModelMixin:list方法实现了获取多个对象
  3. CreateModelMixin:create方法实现了增加一个对象
  4. UpdateModelMixin:update方法实现了单整体更新,partial_udate实现了单局部更新
  5. DestroyModelMixin:destory方法实现了单独删除

一般结合generics工具视图使用

工具视图(generics)

GenericAPIView

GenericAPIView,是generics家族的基类,主要帮我们把qureysetserializer_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--视图家族的更多相关文章

  1. DRF 视图家族及路由层补充

    目录 视图家族 一.views视图类 1.APIView类 2.GenericAPIView类(generics中) 二.mixins类:视图辅助工具 1.RetrieveModelMixin 2.L ...

  2. drf框架 - 视图家族 | GenericAPIView | mixins | generics | viewsets

    视图家族 view:视图 generics:工具视图 mixins:视图工具集 viewsets:视图集 学习曲线: APIView => GenericAPIView => mixins ...

  3. drf序列化组件之视图家族

    一.视图家族的分类 1.导入分类 from rest_framewok import views, generics, mixins, viewsets views:视图类 ​ 两大视图类:APIVi ...

  4. drf序列化高级、自定义只读只写、序列化覆盖字段、二次封装Response、数据库查询优化(断关联)、十大接口、视图家族

    目录 自定义只读 自定义只写 序列化覆盖字段 二次封装Response 数据库关系分析 断外键关联关系 ORM操作外键关系 ORM四种关联关系 基表 系列化类其他配置(了解) 十大接口 BaseSer ...

  5. drf二次封装response-APIViews视图家族-视图工具集-工具视图-路由组件

    视图类传递参数给序列化类 (1).在视图类中实例化 序列化对象时,可以设置context内容. (2).在序列化类中的局部钩子.全局钩子.create.update方法中,都可以用self.conte ...

  6. 视图家族 & 路由组件

    目录 视图家族 & 路由组件 视图集与路由组件 基于 GenericAPIView 的十大接口 基于 generics 包下工具视图类的六大基础接口 视图集 路由组件:必须配合视图集使用 自定 ...

  7. 使用DRF视图集时自定义action方法

    在我们用DRF视图集完成了查找全部部门,创建一个新的部门,查找一个部门,修改一个部门,删除一个部门的功能后,views.py的代码是这样子的: class DepartmentViewSet(Mode ...

  8. 【DRF视图】

    目录 开始使用内置视图 请结合[DRF序列化]此文献中的数据文件及序列化文件来阅读如下代码. DRF视图为我们提供了非常简便的方法--内置了增删改查等一系列的操作. 我们只需在url中指定对应的方法, ...

  9. day73_10_18视图家族与序列化的传参。

    一.序列化传参 在视图类中实例化序列对象时,还有一个参数为context,这个参数是存放字典,将所有从前端传来的数据传输到序列化中,比如需要在序列化中校验当前用户. 传入的request参数也是一个对 ...

  10. DRF视图-请求与响应

    DRF视图 drf的代码简写除了在数据序列化体现以外,在视图中也是可以的.它在django原有的django.views.View类基础上,drf内部封装了许多子类以便我们使用. Django RES ...

随机推荐

  1. 转: angularjs select 赋值 ng-options配置方式

    摘自: http://blog.csdn.net/chwshuang/article/details/53861249 数组方式 数据是数组 $scope.years = [2014, 2015, 2 ...

  2. IE6兼容性bug汇总

    1.终极方法:条件注释 <!--[if lte IE 6]> 这段文字仅显示在 IE6及IE6以下版本. <![endif]--> <!--[if gte IE 6]&g ...

  3. Comet OJ 夏季欢乐赛 完全k叉树

    完全k叉树 https://cometoj.com/contest/59/problem/A?problem_id=2712 题目描述 欢迎报考JWJU!这里有丰富的社团活动,比如为梦想奋斗的ACM集 ...

  4. selenium数据读取模块

    例如 数据保存在txt中 def info(path): web_info={} config = open(path) for line in config: result = [ele.strip ...

  5. KDiff3使用指南

    http://kdiff3.sourceforge.net/ KDiff3 is a diff and merge program that compares or merges two or thr ...

  6. mysql Navicat通过代理链接数据库

    1.做完host 账号 密码(数据库服务器)配置之后,选择ssh 2.配置代理服务器ip的登录的账号密码.(代理服务器必须可以连你的Navicat客户端和数据库服务器,不然怎么做代理.) 3.可以直接 ...

  7. 请用js写一个函数,实现获取浏览器url中查询字符串中的参数并返回一个数组

    <script> console.log(getUrlArr()); function getUrlArr() { var arr = []; var url = "http:/ ...

  8. 牛客NOIP暑期七天营-提高组1

    牛客NOIP暑期七天营-提高组1 链接 A 边权可为0就排序建一条链子. 但是边权不为0 除了第一个有0的不行. x连向上一个比他小的数. 期间判断有无解. #include <bits/std ...

  9. js规范思维导图(仅限于自己)

  10. 安装kafka + zookeeper集群

    系统:centos 7.4 要求:jdk :1.8.x kafka_2.11-1.1.0 1.绑定/etc/hosts 10.10.10.xxx      online-ops-xxx-0110.10 ...