9个视图子类
在此文件中 from rest_framework.generics 有九个视图子类 功能分别如下
9个视图子类---视图类,不需要额外继承GenericAPIView,只需要继承9个中其中某个,就会有某个或某几个接口
CreateAPIView 新增数据接口 post
ListAPIView 获取全部数据 get
RetrieveAPIView 获取单个数据 get
DestroyAPIView 删除单个数据 delete
UpdateAPIView 修改单个数据 put
ListCreateAPIView 获取全部和新增数据 get post
RetrieveUpdateAPIView 查询单个和修改单个 get put
RetrieveDestroyAPIView 查询单个和删除单个 get delete
RetrieveUpdateDestroyAPIView 查询、修改、删除
## 路由
urlpatterns = [
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookView.as_view()),
]
# 视图类
class BookView(ListCreateAPIView): # 查询所有,新增一个
queryset = Book.objects.all()
serializer_class = BookSerializer
# 新增一个,修改一个,删除一个
class BookDetailView(RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
视图集
1.0版本 视图类ModelViewSet与路由层.as_view({'get': 'list'})搭配使用
from rest_framework.viewsets import ModelViewSet
class BookView(ModelViewSet): # 继承了这个以后就相当于拥有了5个功能
queryset = Book.objects.all()
serializer_class = BookSerializer
重点,一旦继承了ModelViewSet那路由写法就要改变为
path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
# 通过键值对来 判断 什么请求方式 执行 什么方法
ModelViewSet分析
这个类又继承了 5个视图扩展类 + GenericViewSet 这个类
GenericViewSet 这个类 又继承了GenericAPIView ViewSetMixin
所以 ModelViewSet 可以拥有 5个功能
但是导致我们更改url写法的是ViewSetMixin
ViewSetMixin分析
ViewSetMixin重写了as_view方法 所以 以后配置路由变为了
views.BookView.as_view({'get': 'list', 'post': 'create'})
这样当路由请求来的时候 其实是执行了ViewSetMixin的as_view方法
@classonlymethod
def as_view(cls, actions=None, **initkwargs):
# 如果没有传actions,直接抛异常,路由写法变了后,as_view中不传字典,直接报错,actions就是路由里面填写的字典
if not actions:
raise TypeError("The `actions` argument must be provided when "
"calling `.as_view()` on a ViewSet. For example "
"`.as_view({'get': 'list'})`")
def view(request, *args, **kwargs):
self = cls(**initkwargs)
self.action_map = actions
for method, action in actions.items():
# 循环对我们传入的字典解压赋值
# method = get action = list
handler = getattr(self, action)
# 通过反射视图类中action对应的方法
# handler就是视图类中的list方法
setattr(self, method, handler)
# 反射修改,把method:get的请求方式变为了执行list方法
return self.dispatch(request, *args, **kwargs)
# 去除了csrf校验
return csrf_exempt(view)
# ViewSetMixin的as_view方法的本质是执行了 view方法
总结
'''
from rest_framework.viewsets下有这几个类
ModelViewSet:5个试图扩展类+ViewSetMixin+GenericAPIView
ReadOnlyModelViewSet::2个试图扩展类+ViewSetMixin+GenericAPIView 只读的两个
ViewSetMixin:魔法,重新了as_view,只要继承他,以后路由写法变成了映射方法
ViewSet:ViewSetMixin+ APIView
GenericViewSet:ViewSetMixin+ GenericAPIView
'''
只要是继承了ViewSetMixin的视图类,路由写法都变为了需要(重写了as_veiw)
actions就是我们传入的字典,通过反射来控制 访问方式执行不同的功能
以后视图类中的方法名,可以任意命名,只要在路由中做好映射即可
eg:
path('user/', views.UserView.as_view({'get': 'login', 'post': 'register'}))
class UserView(GenericViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def login(self,request):
return Response({'code':'100','msg':'登录成功'})
def register(self,request):
pass
# 视图类中的方法名,可以任意命名,只要在路由中做好映射即可
# 如果是跟数据库无关的功能接口 例如 短信验证码 等 尽量使用ViewSet
path('msg/<int:pk>/', views.SendView.as_view({'post': 'send_sms'}))
from rest_framework.viewsets import ViewSet
class SendView(ViewSet):
def send_sms(self, request,pk):
print(pk)
phone = request.query_params.get('phone')
# 手机号,从哪去,假设get请求,携带了参数
print('发送成功,%s' % phone)
return Response({'code': 100, 'msg': '发送成功'})
# 以后,你想继承APIView,但是想变路由写法【视图类中方法名任意命名】,要继承ViewSet
# 以后,你想继承GenericAPIView,但是想变路由写法【视图类中方法名任意命名】,要继承GenericViewSet
路由系统 自动生成
# drf 由于继承ViewSetMinxin类,路由写法变了
-原生+drf,以后的路由写法,可能会有如下情况(三种情况)
-path('books/', views.BookView.as_view()
-path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'}))
-自动生成
如何自动生成路由 -------------------------------------------
#需要 继承ModelViewSet后,路由可以自动生成
from rest_framework.routers import SimpleRouter,DefaultRouter
routers = SimpleRouter()
# 1.通过导入的生成路由的类产生对象
routers.register('user', views.UserView, 'user')
# 2.向对象内注册一个路由 三个参数分别为 路由的地址 路由关联的视图类 路由别名
# 会自动生成 https//127.0.0.1:8000/user/ https//127.0.0.1:8000/user/<int:pk>
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns = urlpatterns + routers.urls
#3.将自动生成的路由添加到django路由中
SimpleRouter与DefaultRouter的区别是:DefaultRouter会多附带一个默认的api根视图 返回一个包含所有列表视图的超链接响应数据
一般都使用SimpleRouter
include写路由
from django.urls import path, include
# 导入该模块
from rest_framework.routers import SimpleRouter,DefaultRouter
routers = SimpleRouter()
routers.register('user', views.UserView, 'user')
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),]
优点:可以自定义路径前缀 建议使用
底层实现:
-本质是自动做映射,能够自动成的前提是,视图类中要有 5个方法其中的某一个或者多个
get--->list
get---->retrieve
put---->update
post---->create
delete---->destory
所以需要搭配视图类继承-ModelViewSet或ReadOnlyModelViewSet或
viewsetMixin+9个视图子类/ViewSetMixin+GenericAPIView+5个试图扩展类
才可以自动生成
eg: class UserView(ViewSetMixin,ListAPIView,RetrieveAPIView):
# 该接口只能读数据
queryset = User.objects.all()
serializer_class = UserSerializer
标签:get,ViewSetMixin,视图,生成,图集,path,路由,view
From: https://www.cnblogs.com/moongodnnn/p/17096584.html