drf 路由的写法和 actions 装饰器的使用
DRF 框架中 路由的写法
使用 drf 框架,在视图层中都是使用 CBV
,基于类的视图函数。书写路由时需要调用 as_view
有三种写法:
1、没有继承ViewSetMixin
的视图与路由对应关系
urlpatterns = [
path('book/', views.BookAPIView.as_view()),
]
2、继承了ViewSetMixin
的视图与路由对应关系
urlpatterns = [
path('book4/', views.BookViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
path('book4/<int:pk>/', views.BookViewSetPk.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'delete'}))
]
3、自动生成第 2 种方法的两条路由,一条不带参数,一条附带整型参数
# 导入 routers 模块
from rest_framework.routers import DefaultRouter, SimpleRouter
# 实例化对象并注册路由
router = DefaultRouter()
router.register('book/', views.BookViewSet, 'book')
# 添加到路由列表中
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls
还有一种添加方式:使用路由分发
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include(router.urls)),
]
DefaultRouter
和 SimpleRouter
的区别
DefaultRouter
比 SimpleRouter
网址多一个根
DefaultRouter:
SimpleRouter:
action 装饰器的使用
由于视图层类继承了 VewSetMixin
,该类重写了 as_view
方法,可以重定义五个接口所调用的方法,比如,我修改 get 请求方式调用的方法不再为ListModelMixin
类中定义的 list
方法,而是我在视图类中定义的 login
函数。
路由层:
urlpatterns = [
path('book4/', views.BookViewSet.as_view(actions={'get': 'login', 'post': 'create'})),
]
视图层:
class BookViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):
queryset = Book.objects
serializer_class = BookModelSerializer
def login(self, request):
print(request.method)
return JsonResponse({'username': 'elijah'})
浏览器发起get请求返回login函数放回json
格式字符串
但我们一般都会选择使用router
模块自动生成路由,而自动生成的路由中 action
参数都是固定写了五个接口请求方法和其对应关系的,如果想指定某个请求方式会调用视图类中重写的函数,就得使用到 action
装饰器。这样便可以生成一条该重写函数的专用api
接口了
action
装饰器的参数:
- methods=请求方法(列表)
- detail=是否带id
- url_path=地址如果不写,默认已方法名为地址
- url_name=别名
写成如下,detail=True
为真,会需要传入一个 pk 值,自动生成路由会生成一条路径:127.0.0.1:8080/book4/pk值/login ,get
和post
请求都会触发
from rest_framework.decorators import action
class BookViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):
queryset = Book.objects
serializer_class = BookModelSerializer
@action(methods=['GET', 'POST'], detail=True)
def login(self, request, pk):
print(request.method)
return JsonResponse({'username': 'elijah'})
浏览器发起的 get
请求:
detail=False
为假,自动生成路由会生成一条路径:127.0.0.1:8080/book4/login
记得把 login 函数的 pk 形参去掉
class BookViewSet(ModelViewSet):
queryset = Book.objects
serializer_class = BookModelSerializer
@action(methods=['GET', 'POST'], detail=False)
def login(self, request):
print(request.method)
return JsonResponse({'username': 'elijah'})
通过action,怎么通过action判断,重写get_queryset,get_serializer_class