视图组件(继承不同类重写视图类第四层和第五层)、路由组件(修改路由的全部写法)
今日内容概要
- 视图组件
- 路由组件
# 9个视图子类--是视图类
from rest_framework.generics import
CreateAPIView,
ListAPIView,
DestroyAPIView,
RetrieveAPIView,
UpdateAPIView,
ListCreateAPIView,
RetrieveUpdateAPIView,
RetrieveUpdateDestroyAPIView,
RetrieveDestroyAPIView
第四层: 通过9个视图子类,重写视图函数 views.py:
# 第四层:通过9个视图子类,重写视图函数
# 9个视图子类
from rest_framework.generics import CreateAPIView, ListAPIView, DestroyAPIView, RetrieveAPIView, UpdateAPIView
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIViewclass PublishView(ListCreateAPIView):# 查询所有和新增接口就有了
# class PublishView(CreateAPIView):# 新增接口就有了
# class PublishView(ListAPIView):# 查询所有接口就有了
queryset = Publish.objects.all()
serializer_class = PublishSerialzierclass PublishDetailView(RetrieveUpdateDestroyAPIView):# 查询单条,删除,修改 接口就都有了
# class PublishDetailView(RetrieveAPIView):# 查询单条 接口就有了
# class PublishDetailView(DestroyAPIView):# 删除 接口就有了
# class PublishDetailView(UpdateAPIView):# 修改 接口就有了
# class PublishDetailView(RetrieveDestroyAPIView):# 查询单条和删除 接口就有了
# class PublishDetailView(RetrieveUpdateAPIView):# 查询单条和更新 接口就有了
# class PublishDetailView(UpdateAPIView,DestroyAPIView):# 更新和删除 接口就有了
queryset = Publish.objects.all()
serializer_class = PublishSerialzier# 但是页有可能要重写--》get_queryset--》get_serializer_class--》perform_create--》get,post等方法
文章图片
第五层: 通过ViewSet,重写视图函数 views.py:
# 第五层:通过ViewSet写视图类
# 5个接口,都用一个视图类----》导致了路由问题:有两个get
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet"""
from rest_framework.viewsets import ViewSet, GenericViewSet
from rest_framework.viewsets import ViewSetMixin
ViewSet=APIView+ViewSetMixin
GenericViewSet=GenericAPIView+ViewSetMixin以后只要想自动生成路由,必须继承ViewSetMixin及其子类
之前的写法可以沿用,只是如果要自动生成路由可以选择继承ViewSet 或者 GenericViewSet
"""
class PublishView(ModelViewSet):# 修改路由,5个接口都有
# 继承了5个视图扩展类+GenericViewSet(ViewSetMixin, generics.GenericAPIView)
# 其中 ViewSetMixin-->控制了路由写法变了# class PublishView(ReadOnlyModelViewSet):# 修改路由,只有 查所有,查单个两个接口
queryset = Publish.objects.all()
serializer_class = PublishSerialzier##### 在urls.py中配置 加入方式一:
from rest_framework.routers import SimpleRouterrouter = SimpleRouter()
router.register('publish', views.PublishView, 'publish')
# 然后要把路由加入到urlpatterns的列表中 两种方式urlpatterns = [
path('admin/', admin.site.urls),path('books/', views.BookView.as_view()),
path('books/', views.BookView.as_view()),
]# 加入方式一
# router.urls他会自动生成列表 包含两种地址: publishs / publishs/
# print(router.urls)# [, ]
urlpatterns += router.urls# 两个列表相加##### 在urls.py中配置 加入方式二:
from django.urls import include
from rest_framework.routers import SimpleRouterrouter = SimpleRouter()
router.register('publish', views.PublishView, 'publish')
# 然后要把路由加入到urlpatterns的列表中 两种方式urlpatterns = [
path('admin/', admin.site.urls),path('books/', views.BookView.as_view()),
path('books/', views.BookView.as_view()),# 加入方式二:
path('api/v1/', include(router.urls)),# from django.urls import include
# 这样写等用于下面两句''引号中可以随意加入前缀# 但是默认就有: publishs / publishs/
# path('api/v1/publishs/', views.PublishView.as_view()),
#
# path('api/v1/publishs/', views.PublishDetailView.as_view()),
]
文章图片
2、路由组件
# 只要继承ViewSetMixin 及其子类,路由写法就变了# 视图类只要继承ViewSetMixin,路由写法就变了 而且视图类中的方法不一定写成get,post.. 可以随意命名 路由改为:
path('login/', views.TestView.as_view({'get': 'login'})),# 意思为:get请求来了,执行视图类中的login方法# 如何执行的?源码分析
ViewSetMixin必须写在前面
as_view--->类的查找顺序
actions就是传入的字典---》view闭包函数:
def view(request, *args, **kwargs):
#getlogin
for method, action in actions.items():
# 把login方法的内存地址给了handler
handler = getattr(self, action)
# 通过反射,设置给get---》对应login---》get请求执行get方法,现在get方法变成了login方法
setattr(self, method, handler)
return self.dispatch(request, *args, **kwargs)# 跟之前一样了
演示继承 ViewSetMixin类 的路由写法:
### views.py中:from rest_framework.viewsets import ViewSetMixin, ViewSet, GenericViewSet
from rest_framework.views import APIView
from rest_framework.decorators import actionclass TestView(ViewSetMixin, APIView):# ViewSetMixin必须写在前面
# class TestView(ViewSet):# 等同于上面 class TestView(ViewSetMixin, APIView)
# class TestView(ViewSetMixin, GenericAPIView):# 只要继承ViewSetMixin的 该类就必须写在前面
def login(self, request):
return Response("get-login")# 路由中 urls.py:
# 路由组件:
path('login/', views.TestView.as_view({'get': 'login'})),# 意思为:get请求来了,执行视图类中的login方法
文章图片
继承ModelViewSet 类,路由写法:
# views.py:# 路由组件
class PublishView(ModelViewSet):# 修改路由,5个接口都有
queryset = Publish.objects.all()
serializer_class = PublishSerialzier# urls.py:path('publish/', views.PublishView.as_view({'get': 'list', 'post': 'create'})),
path('publish/', views.PublishView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
总结:
# 上面的两个路由,是可以自动生成的:
第一步:导入drf提供的路由类
from rest_framework.routers import SimpleRouter 第二步:实例化得到对象
router = SimpleRouter() 第三步:注册路由
router.register('地址', 视图类, '别名')
router.register('publish', views.PublishView, 'publish') 第四步:在urlpatterns加入(两种方式)
path('/api/v1', include(router.urls))
urlpatterns+=router.urls# SimpleRouter类 和 DefaultRouter类
用法完全一样 只是生成的路由不一样
DefaultRouter 比 SimpleRouter多一条根地址,一般咱么就用 SimpleRouter就可以# 如果使用自动生成路由,必须继承谁及其子类?
GenericViewSet + 5个视图扩展类至少之一 才能自动生成# action装饰器
# action装饰器可以再生成路由 记得要修改路由为自动生成模式
from rest_framework.decorators import action
class TestView(ViewSetMixin, APIView):# ViewSetMixin必须写在前面
# action的默认参数:
# methods=请求方法,列表,detail=是否带id,url_path=地址如果不写,默认已方法名为地址,url_name=别名
# 写成如下,自动生成路由会生成一条路由:127.0.0.1:8080/test/login -->get,post都会触发
@action(methods=['GET', 'POST'], detail=False)
def login(self, request):
return Response("get-login")# 如果写法如下,生成的路径是127.0.0.1:8080/test/数字/login
@action(methods=['GET', 'POST'], detail=True)
def login(self, request):# 使用action,怎么通过action判断?
重写 get_queryset、get_serializer_class
class TestView2(GenericViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializerdef get_queryset(self):
# 根据请求地址,返回的get_queryset不一样
if self.action=='login':
return Author.objects.all()
else:
return self.querysetdef get_serializer_class(self):
if self.action=='login':
return AuthorSerialzier
else:
return BookSerializer@action(methods=['GET','POST'],detail=True)
def login(self,request):
obj=self.get_queryset()
return Response("get-login")@action(methods=['GET'], detail=True)
def test1(self,request):
obj = self.get_queryset()
return Response("get-test1")
【视图组件(继承不同类重写视图类第四层和第五层)、路由组件(修改路由的全部写法)】
文章图片
推荐阅读
- springboot实现返回视图而不是string的方法
- 超简单易懂的vue组件传值
- Vue.js通过组件处理Icon图标
- go|Go继承的方法重写,继承抽象类实现
- Java基础|10 继承、super、this、抽象类
- java|java-继承,super关键字,this关键字,抽象方法和抽象类,红包案例分析实现
- JAVA中抽象类是否允许多继承_java学习笔记(12-继承、抽象类)
- flutter开发|Flutter--获取父组件约束大小
- [译]|[译] MDC-104 Flutter(Material 高级组件(Flutter))
- JS的面向对象(理解对象,原型,原型链,继承,类)