目录

1.APIView

2.GenericAPIView:通用视图类

3.5个视图扩展类:ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

4.GenericAPIView的视图子类:ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView

5.视图集基类:ViewSet,GenericViewSet,ModelViewSet,ReadOnlyViewSet

  1.ViewSet

  2.ViewSet+????APIView

  3.GenericViewSet+???Mixin

  4.ModelViewSet

  5.ReadOnlyViewset

6.路由:Routers

  1.如何添加路由数据

  2.在视图集中附加action声明

  3.DefaultRouter和SimpleRouter的区别(了解)

7.创建虚拟环境

附:APIView思维导图

附:drf的执行流程图

APIView

APIView总结

1.APIView中封装了自己的request和response

2.django:request.GET对应drf中的request.query_params

3.django:request.POST对应drf中的request.data

4.APIView中的response不需要写参数safe=False,ensure_ascii这些东西了,因为这些功能已经封装在response里面了

5.当我们在浏览器上访问一个url,给你回复的是一个界面。如果我们用postman访问url,给你返回的就是json数据。这是因为response中有相关配置导致的。

APIView实现代码

class Students1View(APIView):

    # 获取所有数据接口
def get(self,request):
all_data = models.Student.objects.all() # 获取数据库中Student表中所有数据
serializer = StudentSerializer(instance=all_data,many=True) # 将后端数据序列化
return Response(serializer.data) # 将序列化之后的数据传递给前端 # 添加一条记录的接口
def post(self,request): data = request.data # 获取用户在前端输入的数据
serializer = StudentSerializer(data=data) # 将数据反序列化
if serializer.is_valid(): # 校验
instance = serializer.save() # instance为添加的新纪录对象
serializer = StudentSerializer(instance=instance) # 根据API规范,数据保存之后应该显示到前端上,所以需要将新添加的数据序列化 return Response(serializer.data,status=status.HTTP_201_CREATED) else:
print(serializer.errors) class Student1View(APIView): # 获取单条记录
def get(self,request,pk):
stu_obj = models.Student.objects.get(pk=pk)
serializer = StudentSerializer(instance=stu_obj)
return Response(serializer.data) # 更新单条记录
def put(self,request,pk):
stu_obj = models.Student.objects.get(pk=pk)
data = request.data
serializer = StudentSerializer(instance=stu_obj, data=data, partial=True)
if serializer.is_valid():
instance = serializer.save() # instance为添加的新纪录对象
serializer = StudentSerializer(instance=instance)
return Response(serializer.data)
else:
print(serializer.errors) # 删除单条记录
def delete(self,request,pk):
models.Student.objects.get(pk=pk).delete()
return Response(None,status=status.HTTP_204_NO_CONTENT)

GenericAPIView:通用视图类

GenerivAPIView继承自APIView方法,主要增加了操作序列化器和数据库查询的方法。

from rest_framework.generics import GenericAPIView

class Students2View(GenericAPIView,):
queryset = models.Student.objects.all() # 指明要使用的数据查询集[必须指定]
serializer_class = StudentSerializer # 指明视图要使用的序列化器[可写可不写] # 通过get_serializer_class来控制不同条件下,使用不同的序列化器类
def get_serializer_class(self):
if self.request.method == 'GET':
return Student2Serializer
else:
return StudentSerializer # 获取所有数据接口
def get(self, request):
# all_data = models.Student.objects.all()
# serializer = StudentSerializer(instance=all_data, many=True)
serializer = self.get_serializer(instance=self.get_queryset(), many=True)
return Response(serializer.data) # 添加一条记录的接口
def post(self, request):
data = request.data
serializer = self.get_serializer(data=data)
if serializer.is_valid():
instance = serializer.save() # instance为添加的新纪录对象
serializer = self.get_serializer(instance=instance) return Response(serializer.data, status=status.HTTP_201_CREATED) else:
print(serializer.errors)
return Response({'error':'字段错误'}) class Student2View(GenericAPIView):
queryset = models.Student.objects.all()
serializer_class = StudentSerializer # 获取单条记录
def get(self, request, pk):
# stu_obj = models.Student.objects.get(pk=pk)
serializer = self.get_serializer(instance=self.get_object())
return Response(serializer.data) # 更新单条记录
def put(self, request, pk):
# stu_obj = models.Student.objects.get(pk=pk)
data = request.data
serializer = self.get_serializer(instance=self.get_object(), data=data, partial=True)
if serializer.is_valid():
# print('>>>',serializer.data) #在save方法之前,不能调用data属性,serializer.data
instance = serializer.save() # instance为添加的新纪录对象
print(serializer.data) #之后可以看
serializer = self.get_serializer(instance=instance) return Response(serializer.data)
else:
print(serializer.errors) # 删除单条记录 def delete(self, request, pk): models.Student.objects.get(pk=pk).delete()
return Response(None, status=status.HTTP_204_NO_CONTENT)

GenericAPIView中的属性和方法

serializer_class 指明视图使用的序列化器

get_serializer(self, *args, **kwargs) 返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法

queryset 指明使用的数据查询集

get_queryset(self) 返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写

get_object(self) 返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。在视图中可以调用该方法获取详情信息的模型类对象。

get_serializer_class(self) 当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。

            返回序列化器类,默认返回serializer_class

5个视图扩展类:ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

提供了几种后端视图(对数据资源进行增删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。

这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

换句话说。就是你在视图中的get post put等这些方法中不用写里面的代码了,里面的代码相关的操作已经被封装到对应的Mixin中了。

class Students3View(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset = models.Student.objects.all()
serializer_class = StudentSerializer # 获取所有数据接口
def get(self, request):
return self.list(request) # 添加一条记录的接口
def post(self, request):
return self.create(request) class Student3View(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = models.Student.objects.all()
serializer_class = StudentSerializer # 获取单条记录
def get(self, request, pk):
return self.retrieve(request, pk) # 更新单条记录
def put(self, request, pk):
return self.update(request, pk) # 删除单条记录
def delete(self, request, pk):
return self.destroy(request, pk)

GenericAPIView的视图子类:ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView

上面的代码还是过于麻烦,因为既要继承GenericAPIView又要继承Mixin系列的类。

所以将各自的操作封装成自己的APIView类。用哪个继承哪个。

而且连函数都不用写了,在???APIView类中已经有了,所以不用再写了,继承自己的APIView类即可。

from rest_framework.generics import ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView

class Students4View(ListAPIView,CreateAPIView):
queryset = models.Student.objects.all()
serializer_class = StudentSerializer class Student4View(RetrieveAPIView,UpdateAPIView,DestroyAPIView):
queryset = models.Student.objects.all()
serializer_class = StudentSerializer

视图集基类:ViewSet,GenericViewSet,ModelViewSet,ReadOnlyViewSet

ViewSet

主要解决问题:之前我们在写视图类的时候,获取多条数据和提交数据放在了一个类中。获取单条数据,更新单条数据,删除多条数据放到了一个类中

这是因为多条数据操作时不需要指定pk值,而针对单条数据时,需要指定pk值。也就是说需要知道你要操作哪一条数据

这样我们就很矛盾。我们没法将5个方法放到同一个类中。

而下面的ViewSet就可以解决这个问题,将5个方法放到同一个类中

from rest_framework.viewsets import ViewSet

class Students5View(ViewSet):
# 获取所有数据接口
def get_all_student(self,request): # action
all_data = models.Student.objects.all()
serializer = StudentSerializer(instance=all_data,many=True)
return Response(serializer.data) # 添加一条记录的接口
def add_student(self,request):
data = request.data
serializer = StudentSerializer(data=data)
if serializer.is_valid():
instance = serializer.save() #instance为添加的新纪录对象
serializer = StudentSerializer(instance=instance) return Response(serializer.data,status=status.HTTP_201_CREATED) else:
print(serializer.errors) def get_one(self,request,pk):
stu_obj = models.Student.objects.get(pk=pk)
serializer = StudentSerializer(instance=stu_obj)
return Response(serializer.data)

通过上面代码我们可以看出。单条数据操作和多条数据被放到了一个类中。并且方法名也不再局限于必须要使用get post put...这些方法名了。

这是因为在urls.py中的as_view方法做了一个请求方法和对应函数名的指定

而获取单条数据和获取多条数据能够共存在一个类中,是因为他们处于两个url中。虽然都是get请求过去的,但是他们在不同的url中,会执行各自的视图方法

通过下面url,我们就可以发挥出ViewSet的用处了:

path('students5/', views.Students5View.as_view({'get':'get_all_student','post':'add_student'})),
re_path('students5/(?P<pk>\d+)/', views.Students5View.as_view({'get':'get_one'})),

ViewSet+????APIView

用我们刚才学的ViewSet和之前的???APIView做一个结合~

效果:即放到了一个类中,而且各个方法里不用写详细代码(????APIView的作用)

"""发挥下ViewSet的作用"""
from rest_framework.viewsets import ViewSet
from rest_framework.generics import ListAPIView,CreateAPIView,RetrieveAPIView
class Student2ViewSet(ViewSet,ListAPIView,CreateAPIView,RetrieveAPIView):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer

def get_all(self,request):
return self.list(request) def add_student(self,request):
return self.create(request) def get_one(self,request,pk):
return self.retrieve(request)

GenericViewSet+???Mixin

效果和Viewset+???APIView是相同的

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin
class Student3ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
def get_all(self,request):
return self.list(request) def add_student(self,request): return self.create(request) def get_one(self,request,pk):
return self.retrieve(request)

现在我们的代码是这个样子的。美中不足是我们还需要自己写def方法,其实我们希望的是类里面没有def方法的

其实。这个需求刚才在前面已经提到了。

只需要在urls.py中将get post put这类请求类型直接与Mixin中内置的list,create,update等动作方法关联起来。

这样它就会自动去执行里面的list,create,update方法。不需要你在视图里定义一个函数名称然后再return self.create()了

urls.py如下所示:

urlpatterns = [
path("students7/", views.Student4ViewSet.as_view({"get": "list", "post": "create"})),
re_path("students7/(?P<pk>\d+)/", views.Student4ViewSet.as_view({"get": "retrieve","put":"update","delete":"destroy"})),
]

url直接就是{请求类型:action动作名},这样我们在视图那一块的代码又可以缩减了。函数全部无需定义了。

经过改良后,视图代码如下所示:

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
class Student4ViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer

ModelViewSet

上面的代码,在导入和继承的时候太麻烦了,需要写5个Mixin类

这时出现了ModelViewSet,ModelViewSet同时继承ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin这五个类。

这样写起来就更加简单了。

终极版如下所示:

from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
from rest_framework.decorators import action
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer

ReadOnlyViewset

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

视图集中定义附加action动作

在视图集中,除了上述默认的方法动作外,还可以添加自定义动作,进行扩展。

举例,比如做一个登录方法login:

from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer def login(self,request): # 这个就可以称为自定义的action动作
"""学生登录功能"""
return Response({"message":"登录成功"})

urls.py这样写

urlpatterns = [
path("students8/", views.StudentModelViewSet.as_view({"get": "list", "post": "create"})),
re_path("students8/(?P<pk>\d+)/",
views.StudentModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), path("stu/login/",views.StudentModelViewSet.as_view({"get":"login"})) ]

在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。

from rest_framework.viewsets import ModelViewSet
from students.models import Student
from .serializers import StudentModelSerializer
from rest_framework.response import Response
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer def get_new_5(self,request):
"""获取最近添加的5个学生信息"""
# 操作数据库
print(self.action) # 获取本次请求的视图方法名 '''通过路由访问到当前方法中.可以看到本次的action就是请求的方法名'''

路由:Routers

如何添加路由数据

如何添加路由数据,并且和视图函数做关联:

from django.urls import path, re_path
from . import views
urlpatterns = [
...
] """使用drf提供路由类router给视图集生成路由列表"""
# 实例化路由类
# drf提供一共提供了两个路由类给我们使用,他们用法一致,功能几乎一样
from rest_framework.routers import DefaultRouter
router = DefaultRouter() # 注册视图集
# router.register("路由前缀",视图集类)
router.register("router_stu",views.StudentModelViewSet) # 把生成的路由列表追加到urlpatterns
urlpatterns += router.urls

上面的代码就成功生成了路由地址[增/删/改/查一条/查多条的功能],但是不会自动帮我们在视图集自定义方法的路由。

所以我们如果也要给自定义方法生成路由,则需要进行action动作的声明。

在视图集中附加action声明

在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action装饰器。

以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。

action装饰器可以接收两个参数:

  • methods: 声明该action对应的请求方式,列表传递

  • detail:

    声明该action的路径是否与单一资源对应,及是否是

    xxx/<pk>/action方法名/
    • True 表示路径格式是xxx/<pk>/action方法名/

    • False 表示路径格式是xxx/action方法名/

from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer # methods 设置当前方法允许哪些http请求访问当前视图方法
'''detail 设置当前视图方法是否是操作一个数据'''
# detail为True,表示路径名格式应该为 router_stu/{pk}/login/
@action(methods=['get'], detail=True)
def login(self, request,pk):
"""登录"""
... # detail为False 表示路径名格式应该为 router_stu/get_new_5/
@action(methods=['put'], detail=False)
def get_new_5(self, request):
"""获取最新添加的5个学生信息"""
...

DefaultRouter和SimpleRouter的区别(了解)

DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。

比如使用DefaultRouter时你访问一下http://127.0.0.1:8001/router_stu/ 会看到一个页面。

而SimpleRouter会报错,一般都需要有个查看所有接口的页面,所以我们基本都是用的是DefaultRouter

创建虚拟环境

1.安装虚拟环境

# 1.管理员方式打开终端

# 2.安装虚拟环境
pip install virtualenv -i https://pypi.douban.com/simple # 3.终端关闭,再重新打开 # 4.注意:创建[环境名称]文件夹,放置所有的环境,进入指定目录 D:/envs # 5.创建虚拟环境
virtualenv 环境名称 'C:\python\python3.6.exe' '''这样写的前提是你的电脑已经将python加入到环境变量中'''
virtualenv 环境名称 --python=python3.6

2.激活虚拟环境

# 1.进入到虚拟环境文件夹下的Scripts目录
activate '''激活虚拟环境''' # 2.退出虚拟环境
deactivate '''退出虚拟环境'''

3.在虚拟环境中安装模块

# 1.激活虚拟环境

# 2.在激活的虚拟环境中安装模块
pip3 install django==2.2 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com # 3.搭建项目环境,在pycharm选择解释器时,选择你之前已经创建好的虚拟环境

4.在pycharm上使用虚拟环境

附:APIView思维导图

附:drf的执行流程图

day73:drf:drf视图相关类&路由Routers&创建虚拟环境的更多相关文章

  1. drf之视图类与路由

    视图 Django REST framwork 提供的视图的主要作用: 控制序列化器的执行(检验.保存.转换数据) 控制数据库查询的执行 2个视图基类 APIView rest_framework.v ...

  2. DRF的视图和路由

    DRF的视图 APIView Django中写CBV的时候继承的是View,rest_framework继承的是APIView, urlpatterns = [ url(r'^book$', Book ...

  3. DRF视图集的路由设置

    在使用DRF视图集时,往往需要配一大堆路由,例如: # views.py class DepartmentViewSet(ListModelMixin,CreateModelMixin,Retriev ...

  4. DRF 的视图,路由和渲染器

    DRF 的视图,路由和渲染器 1 视图 简单的增删改查 : ModelViewSet; 复杂的操作使用APIView 和 GenericViewSet APIView(View) class Home ...

  5. DRF教程4-视图集和路由类

    rest框架包括一个处理viewset的抽象,允许开发人员集中精力处理api交互和建模,url构造都根据常见方式自动处理. ViewSet类 几乎和VIew类一样,不过它提供read,update这样 ...

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

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

  7. DRF中五大扩展类及视图集的介绍

    五个扩展类 (1)ListModelMixin 列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码. 该Mixin的list方法会对 ...

  8. DRF (Django REST framework) 中的视图扩展类

    2. 五个扩展类 1)ListModelMixin 列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码. 该Mixin的list方法 ...

  9. DRF框架(五)——context传参,二次封装Response类,两个视图基类(APIView/GenericAPIView),视图扩展类(mixins),子类视图(工具视图),视图集(viewsets),工具视图集

    复习 1.整体修改与局部修改 # 序列化get (给前端传递参数) #查询 ser_obj = ModelSerializer(model_obj) #只传递一个参数,默认是instance的参数,查 ...

随机推荐

  1. 复习 | 重温jQuery和Zepto的API

    jq和zepto很相似有许多共同的api,zepto也出了很多与jq不一样的api,总的来说,两者更相似,但是zepto更轻量一点,正好公司也在用,复习这两个没错 jq中的zepto的事件和ajax我 ...

  2. springboot之logback配置

    参考了https://blog.csdn.net/hxtxgfzs/article/details/79488163 Spring Boot默认情况下,当使用"Starters" ...

  3. thinkPHP5.1 MVC架构使用方法

    MVC架构 1.M层:model(模型),是增强版的数据库 M层是用来存放自动完成代码.修改器(数据修改).模型事件.验证器 2.V层:view 显示视图 V层用来存放HTML.css.JavaScr ...

  4. 6.Kafka消息流处理

  5. Windows10数字权利永久激活教程

    很多人用Windows10系统,但是没有办法激活,这个教程一定会让你永久激活windows10系统(并非ksm)   打开设置,查看是否激活   如果激活的话,先退掉秘钥,在Windows power ...

  6. CF1120 A. Diana and Liana

    Description At the first holiday in spring, the town Shortriver traditionally conducts a flower fest ...

  7. myisamchk是用来做什么的?MyISAM Static和MyISAM Dynamic有什么区别?

    myisamchk是用来做什么的? 它用来压缩MyISAM[歌1] 表,这减少了磁盘或内存使用. MyISAM Static和MyISAM Dynamic有什么区别? 在MyISAM Static上的 ...

  8. 优雅的在React组件中注册事件

    前言 在React的开发中,我们经常需要在 window 上注册一些事件, 比如按下 Esc 关闭弹窗, 按上下键选中列表内容等等.比较常见的操作是在组件 mount 的时候去 window 上监听一 ...

  9. HTTP 的前世今生,那些不为人知的秘密

    每个时代,都不会亏待会学习的人. 大家好,我是 yes. HTTP 协议在当今的互联网可谓是随处可见,一直默默的在背后支持着网络世界的运行,对于我们程序员来说 HTTP 更是熟悉不过. 平日里我们都说 ...

  10. ZooKeeper-3.5.6分布式锁

    原理 基本方案是基于ZooKeeper的临时节点与和watch机制.当要获取锁时在某个目录下创建一个临时节点,创建成功则表示获取锁成功,创建失败则表示获取锁失败,此时watch该临时节点,当该临时节点 ...