视图组件与路由组件
视图组件与路由组件
一 视图组件
1 drf视图类
# Django REST framwork 提供的视图的主要作用:
控制序列化器的执行(检验、保存、转换数据)
控制数据库查询的执行
2 2个视图基类
2.1 DRF视图基类
# REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。
2.2 视图基类的基本情况
2.2.1 APIView
1) # APIView:继承了原生Django的View, 是REST framework提供的所有视图的基类
2) # APIView与View的不同之处在于:
-传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
-视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
-任何APIException异常都会被捕获到,并且处理成合适的响应信息;
-在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
3) #支持定义的类属性
-authentication_classes 列表或元祖,身份认证类
-permissoin_classes 列表或元祖,权限检查类
-throttle_classes 列表或元祖,流量控制类
4) #基本使用:
-在APIView中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法。
2.2.2 GenericAPIView通用视图类
1) # GenericAPIView:继承了APIView
# 主要增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。
2) # 提供的关于序列化器使用的属性与方法
2.1) #属性
-queryset = models.Book.objects.all() # 指明使用的数据查询集
-serializer_class = serializer.BookModelSerializer # 指明视图使用的序列化器
2.2) #方法
-get_queryset(self):获取配置的queryset
# 返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,
-get_object(self):路由中的分组字段必须是pk
# 返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。
# 在视图中可以调用该方法获取详情信息的模型类对象。
# 若详情访问的模型类对象不存在,会返回404。
# 该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。
-get_serializer(self, *args, **kwargs):
# 返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。
2.2.3 总结**
# APIView:继承了原生Django的View
# GenericAPIView:继承了APIView
# 最终总结
# 两个基类
APIView:如果跟models没有关系(没有数据库相关操作),就继承它
GenericAPIView:有关数据库操作,queryset 和serializer_class
2.3 使用示例:APIView
models
class Book(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=32, null=True)
price = models.DecimalField(max_digits=5, decimal_places=2, null=True)
publish = models.CharField(max_length=32, null=True)
serializer.py
from app01 import models
from rest_framework import serializers
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = '__all__'
view
### 继承了APIView
class BookAPIView(APIView):
def get(self, request):
book_list = models.Book.objects.all()
ser = serializer.BookModelSerializer(book_list, many=True)
return Response(ser.data)
def post(self, request):
ser = serializer.BookModelSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response('成功!')
class BookDetailAPIView(APIView):
def get(self, request, pk):
book = models.Book.objects.get(id=pk)
ser = serializer.BookModelSerializer(book)
return Response(ser.data)
def put(self, request, pk):
book = models.Book.objects.get(id=pk)
ser = serializer.BookModelSerializer(book, data=request.data)
if ser.is_valid():
ser.save()
return Response('修改成功')
def delete(self, requset, pk):
models.Book.objects.filter(id=pk).delete()
return Response('删除成功')
2.4 使用示例:GenericAPIView
models
# 同上
serializer
# 同上
view
## 继承了GenericAPIView
class BookGenericView(GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
def get(self, request, *args, **kwargs):
obj = self.get_queryset()
ser = self.get_serializer(obj, many=True)
return Response(ser.data)
def post(self, request, *args, **kwargs):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response('成功')
class BookDetailGenericView(GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
def get(self, request, *args, **kwargs):
obj = self.get_object()
ser = self.get_serializer(obj)
return Response(ser.data)
def put(self, request, *args, **kwargs):
obj = self.get_object()
ser = self.get_serializer(obj, data=request.data)
if ser.is_valid():
ser.save()
return Response('修改成功')
def delete(self, request, *args, **kwargs):
self.queryset.filter(id=kwargs.get('pk')).delete()
return Response('删除成功')
3 5个视图扩展类
3.1 五个视图扩展类及其作用
3.1.1 5个视图扩展类
# (rest_framework.mixins)
1) CreateModelMixin: create方法创建一条
-提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。
2) DestroyModelMixin: destory方法删除一条
-提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
3) ListModelMixin: list方法获取所有
-提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。【该Mixin的list方法会对数据进行过滤和分页。】
4) RetrieveModelMixin: retrieve获取一条
-提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。
5) UpdateModelMixin: update修改一条
-提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
3.1.2 作用:
-提供了几种后端视图(对数据资源进行增删改查)处理流程的实现,如果需要编写的视图属于这五种,则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。
-这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

3.2 自定义视图扩展类
# 自定义视图扩展类
class ListView():
def get(self, request, *args, **kwargs):
obj = self.get_queryset()
ser = self.get_serializer(obj, many=True)
return Response(ser.data)
class CreateView():
def post(self, request, *args, **kwargs):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
ser.save()
return Response('成功')
class BookGenericView(GenericAPIView, ListView, CreateView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
class RetrieveView():
def get(self, request, *args, **kwargs):
obj = self.get_object()
ser = self.get_serializer(obj)
return Response(ser.data)
class UpdateView():
def put(self, request, *args, **kwargs):
obj = self.get_object()
ser = self.get_serializer(obj, data=request.data)
if ser.is_valid():
ser.save()
return Response('修改成功')
class DestotyView():
def delete(self, request, *args, **kwargs):
self.queryset.filter(id=kwargs.get('pk')).delete()
return Response('删除成功')
class BookDetailGenericView(GenericAPIView, RetrieveView, UpdateView, DestotyView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
3.3 使用drf提供的视图扩展类
##5个视图扩展类
from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin
class BookGenericAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
class BookDetailGenericAPIView(GenericAPIView, DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
4 9个子类视图
4.1 9个子类视图及其方法
#(rest_framework.generics)
1) CreateAPIView:
-继承CreateModelMixin,GenericAPIView
-有post方法,新增数据
2) DestroyAPIView:
-继承DestroyModelMixin,GenericAPIView
-有delete方法,删除数据
3) ListAPIView:
-继承ListModelMixin,GenericAPIView
-有get方法获取所有
4) UpdateAPIView:
-继承UpdateModelMixin,GenericAPIView
-有put和patch方法,修改数据
5) RetrieveAPIView:
-继承RetrieveModelMixin,GenericAPIView
-有get方法,获取一条
>>-----------------------------------<<
6) ListCreateAPIView:
-继承ListModelMixin,CreateModelMixin,GenericAPIView
-有get获取所有,post方法新增
7) RetrieveDestroyAPIView:
-继承RetrieveModelMixin,DestroyModelMixin,GenericAPIView
-有get方法获取一条,delete方法删除
8) RetrieveUpdateAPIView:
-继承RetrieveModelMixin,UpdateModelMixin,GenericAPIView
-有get获取一条,put,patch修改
9) RetrieveUpdateDestroyAPIView:
-继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView
-有get获取一条,put,patch修改,delete删除
4.2 使用示例
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateAPIView, RetrieveDestroyAPIView, RetrieveUpdateDestroyAPIView
# # class BookGenericAPIView(CreateAPIView):
# # class BookGenericAPIView(ListAPIView):
class BookGenericAPIView(ListCreateAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
# # class BookDetailGenericAPIView(RetrieveAPIView):
# # class BookDetailGenericAPIView(RetrieveAPIView,UpdateAPIView):
class BookDetailGenericAPIView(RetrieveUpdateDestroyAPIView):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
5 视图集类
#视图集类
# ViewSetMixin:重写了as_view
# ViewSet: 继承ViewSetMixin和APIView
# GenericViewSet:继承ViewSetMixin, generics.GenericAPIView
# ModelViewSet:继承mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet
# ReadOnlyModelViewSet:继承mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet
5.1 关于视图集类
-使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
·list() 提供一组数据
·retrieve() 提供单个数据
·create() 创建数据
·update() 保存数据
·destory() 删除数据
-ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。
-视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。
5.2 ViewSet与GenericViewSet
5.2.1 ViewSetMixin
# 源码
class ViewSetMixin:
"""
This is the magic.
Overrides `.as_view()` so that it takes an `actions` keyword that performs the binding of HTTP methods to actions on the Resource.
For example, to create a concrete view binding the 'GET' and 'POST' methods to the 'list' and 'create' actions...
view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
"""
5.2.2 ViewSet
-继承ViewSetMixin 【重写了as_view 】 和APIView
-作用与APIView基本类似,提供了身份认证、权限校验、流量管理等。
-ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{‘get’:’list’})的映射处理工作。
-在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
# 源码
class ViewSet(ViewSetMixin, views.APIView):
"""
The base ViewSet class does not provide any actions by default.
"""
pass
5.2.3 GenericViewSet
-继承ViewSetMixin, generics.GenericAPIView
-在实现了调用as_view()时传入字典(如{'get':'list'})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。
-使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖于 GenericAPIView,所以还需要继承GenericAPIView。
# 源码
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
"""
The GenericViewSet class does not provide any actions by default, but does include the base set of generic view behavior, such as the `get_object` and `get_queryset` methods.
"""
pass
5.3 ModelViewSet与ReadOnlyModelViewSet
5.3.1 ModelViewSet
-继承GenericViewSet
-同时包括了mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin
5.3.2 ReadOnlyModelViewSet
-继承GenericViewSet
-同时包括了GenericViewSetmixins.RetrieveModelMixin,mixins.ListModelMixin,
5.4 视图集类之action的使用**
5.4.1 action 的作用
-在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。
5.4.2 action的用法
# 只要继承了ViewSetMixin类
# 路由配置:path('books_mix/', views.BookView.as_view({'get':'lqz'}))
# 视图类的方法中就会有个action
class BookView(ViewSet):
def lqz(self,request,*args,**kwargs):
print(self.action)
return Response('lqz')
# ViewSetMixin以后只要继承它,路由的配置就发生变化了,只需要写映射即可
5.4.3 使用示例-action
url
path('books_mix1', views.BookView.as_view({'get': 'lxx'})),
path('books_mix2', views.BookView.as_view({'get': 'exon'})),
views
from rest_framework.viewsets import ViewSetMixin, ViewSet
# class BookView(ViewSetMixin, APIView):
class BookView(ViewSet):
def lxx(self, request, *args, **kwargs):
print(self.action) # lxx
return Response('lxx')
def exon(self, request, *args, **kwargs):
return Response('exon')
5.4.4 使用示例-ModelViewSet
url
## 路由
## 使用视图集
path('books_set/', views.BookSetView.as_view({'get': 'list', 'post': 'create'})),
# # path('books_set/', views.BookSetView.as_view()), # 直接报错
re_path('^books_set/(?P<pk>\d+)', views.BookSetView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
views
# 继承一个东西,有5个接口
from rest_framework.viewsets import ModelViewSet
from rest_framework.viewsets import ReadOnlyModelViewSet # 只有查询
from rest_framework.views import APIView
class BookSetView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
二 路由组件
1 路由Routers
# 自动生成路由:REST framework提供了两个router, 来帮助我们快速实现路由信息。
-SimpleRouter
-DefaultRouter
# 配置路由的三种方式
1)-最原始的
-path('books/', views.BookAPIView.as_view()),
2)-ViewSetMixin的视图类
-path('books_set/', views.BookSetView.as_view({'get':'list','post':'create'}))
3)-ViewSetMixin的视图类
-自动生成,见下面:Routers自动生成路由
2 自动生成路由的两种方法
2.1 Routers自动生成路由
# 继承了ViewSetMixin的视图类,以后写路由,可以自动生成
from rest_framework import routers
# 实例化得到一个对象
router = routers.SimpleRouter()
# 注册进路由
router.register('books', views.BookSetView)
# 把自动生成的路由配置到urlpatterns中
-urlpatterns += router.urls
-re_path(r'v1/', include(router.urls))
2.2 action装饰器自动生成路由
# action
-当自动生成路由的时候,如果视图类中还有【其它方法】,是无法自动生成路由的
-加action装饰器:
-methods:什么请求方式会触发被装饰函数的执行
-detail:是True是基于带id的路由生成的,如果是False,是基于不带id的路由生成的
-@action(methods=['get'], detail=True)
2.3 自动生成路由的配置方式
urls
from rest_framework import routers
# 实例化得到一个对象
router = routers.SimpleRouter()
# router = routers.DefaultRouter()
router.register('books', views.BookSetView, basename='book') # basename='book'是别名
print(router.urls)
# [<URLPattern '^books/$' [name='book-list']>,
# <URLPattern '^books/lxx/$' [name='book-lxx']>,
# <URLPattern '^books/(?P<pk>[^/.]+)/$' [name='book-detail']>,
# <URLPattern '^books/(?P<pk>[^/.]+)/login/$' [name='book-login']>]
urlpatterns = []
urlpatterns += router.urls
2.4 action装饰器的使用
views
from rest_framework.decorators import action
class BookSetView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = serializer.BookModelSerializer
@action(methods=['get'], detail=True)
def login(self, request, *args, **kwargs):
print(args) # ()
print(kwargs) # {'pk': '5'}
print(self.action) # login
return Response('XXXX')
@action(methods=['post'], detail=False)
def lxx(self, request, *args, **kwargs):
print(self.action) # lxx
return Response('lxx')

浙公网安备 33010602011771号