两个视图基类APIView、GenericAPIView
1、APIView类:
APIView
是REST framework提供的所有视图的基类,继承自Django的View
父类。
APIView
与View
的不同之处在于:
- 传入到视图方法中的是REST framework的
Request
对象,而不是Django的HttpRequeset
对象; - 视图方法可以返回REST framework的
Response
对象,视图会为响应数据设置(render)符合前端要求的格式; - 任何
APIException
异常都会被捕获到,并且处理成合适的响应信息; - 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
支持定义的属性
- authentication_classes 列表或元祖,身份认证类
- permissoin_classes 列表或元祖,权限检查类
- throttle_classes 列表或元祖,流量控制类
基于APIView类写的接口:
class BooksView(APIView): def get(self, request): book_list = Book.objects.all() book_ser = Bookserialisers(book_list, many=True) return Response(book_ser.data) def post(self, request): book_ser = Bookserialisers(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'code': '101', 'msg': '添加失败', 'data': book_ser.errors}) class BookView(APIView): def get(self, request, pk): book = Book.objects.filter(pk=pk).first() book_ser = Bookserialisers(book) return Response(book_ser.data) def put(self, request, pk): book = Book.objects.filter(pk=pk).first() book_ser = Bookserialisers(instance=book, data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response(book_ser.errors) def delete(self, request, pk): ret = Book.objects.filter(pk=pk).delete() return Response({'status': 100, 'msg': '删除成功'})
2、GenericAPIView
(1)继承APIView类,加入了操作序列化器和数据库操作方法。基于GenericAPIView类的接口如下
from rest_framework.generics import GenericAPIView
''' 属性 queryset:指明使用的数据查询集 serializer_class:指明当前视图函数使用的序列化器 方法: get_queryset():返回的是数据库查询结果集,一般数据查询结果有多条数据的时候使用该方法 get_object():返回的是数据库查询结果(单条),一般是查询结果数据只用一条的时候使用该方法。 get_serializer:返回序列化对象 ''' # GenericAPIView接口 class Books1View(GenericAPIView): queryset = Book.objects serializer_class = Bookserialisers def get(self, request): #get_queryset()方法返回的是数据库查询结果集 book = self.get_queryset() #返回序列化对象 book_ser = self.get_serializer(book, many=True) return Response(book_ser.data) def post(self, request): book_ser = self.get_serializer(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'msg': '添加失败'}) class Book1View(GenericAPIView): queryset = Book.objects serializer_class = Bookserialisers def get(self, request, pk): #get_boject()返回的是数据库查询结果。 book = self.get_object() book_ser = self.get_serializer(book) return Response(book_ser.data) def put(self, request, pk): book = self.get_object() book_ser = self.get_serializer(instance=book, data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response(book_ser.errors) def delete(self, request, pk): book = self.get_object().delete() return Response({'msg': '删除成功'})
基于GenericAPIView类的五个视图扩展类
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, RetrieveModelMixin,DestroyModelMixin
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateAPIView,RetrieveUpdateDestroyAPIView,RetrieveDestroyAPIView
这五个类将5个接口分别进行了封装
类名 | 方法(需要传参数) | 请求方法 |
ListModelMixin | list() | get(查询所有) |
CreateModelMixin | create() | post |
UpdateModelMixin | update() | put |
RetrieveModelMixin | retrieve() | get(查询单个) |
DestroyModelMixin | destroy() | delete |
基于五个扩展类的接口
# 五个扩展类 class Books2View(ListModelMixin, GenericAPIView, CreateModelMixin): queryset = Book.objects serializer_class = Bookserialisers def get(self, request): return self.list(request) def post(self, request): return self.create(request) class Book2View(GenericAPIView, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin): queryset = Book.objects serializer_class = Bookserialisers 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)
注意: GenericViewSet + 五个扩展类接口等价与视图集功能
#注册 class Register(GenericViewSet,CreateModelMixin): queryset = models.E_User.objects.all() serializer_class = User_ser #查询 class Search(GenericViewSet,RetrieveModelMixin): queryset = models.E_User.objects.all() serializer_class = User_ser #更新 class Update(GenericViewSet,UpdateModelMixin): queryset = models.E_User.objects.all() serializer_class = User_ser #等价于 class update(ModelViewSet)
GenericAPIView视图九个子类:
类名 | 方法: |
ListAPIView | get() |
CreateAPIView | create() |
RetrieveUpdateAPIView | retrieve() |
DestroyAPIView | delete() |
UpdateAPIView | update |
ListCreateAPIView | list(),create(),patch() |
RetrieveUpdateAPIView | retrieve(),update(),patch() |
RetrieveDestroyAPIView | retrieve(),destroy(),patch() |
RetrieveUpdateDestroyAPIView | retrieve(),update(),destroy(),patch() |
#查询所有书籍和添加书籍 class Books_zuhe(ListCreateAPIView): queryset = Book.objects serializer_class = Bookserialisers #书籍的查删改 class Book_zuhe(RetrieveUpdateDestroyAPIView): queryset = Book.objects serializer_class = Bookserialisers
注意:非视图集的视图接口类,在路由配置中,都是url(r'链接‘,视图类.as_view)
视图集
ReadOnlyModelViewSet: 获取一条或者多条接口
GenericViewSet:ViewSetMixin+GenericApiView
ViewSet:ViewSetMixin+ApiView
ModelViewSet继承了GenericViewSet,重写了as_view()方法,提供了action方法。除了默认的五个接口方法外,还可以自己定义新的方法:
路由文件urls
urlpatterns = [ url(r'^books/latest/$', views.BookViewSet.as_view({'get': 'latest'})), url(r'^books/(?P<pk>d+)/$', views.BookViewSet.as_view({'get': 'retrieve'})), url(r'books3/', views.BookViewSet.as_view(actions={'get':'list','post':'create'})), url(r'book3/(?P<pk>d+)', views.BookViewSet.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})), ]
基于ModelViewSet类接口代码
#ModelViewSet接口 class BookViewSet(ModelViewSet): queryset = Book.objects serializer_class = Bookserialisers def latest(self, request): """ 返回最新的图书信息 """ book = Book.objects.latest('id') serializer = self.get_serializer(book) return Response(serializer.data) def read(self, request, pk): """ 修改图书的阅读量数据 """ book = self.get_object() book.bread = request.data.get('read') book.save() serializer = self.get_serializer(book) return Response(serializer.data)
视图总结:
#两个基类 APIView GenericAPIView:有关数据库操作,queryset 和serializer_class #5个视图扩展类(rest_framework.mixins) CreateModelMixin:create方法创建一条 DestroyModelMixin:destory方法删除一条 ListModelMixin:list方法获取所有 RetrieveModelMixin:retrieve获取一条 UpdateModelMixin:update修改一条 #9个子类视图(rest_framework.generics) CreateAPIView:继承CreateModelMixin,GenericAPIView,有post方法,新增数据 DestroyAPIView:继承DestroyModelMixin,GenericAPIView,有delete方法,删除数据 ListAPIView:继承ListModelMixin,GenericAPIView,有get方法获取所有 UpdateAPIView:继承UpdateModelMixin,GenericAPIView,有put和patch方法,修改数据 RetrieveAPIView:继承RetrieveModelMixin,GenericAPIView,有get方法,获取一条 ListCreateAPIView:继承ListModelMixin,CreateModelMixin,GenericAPIView,有get获取所有,post方法新增 RetrieveDestroyAPIView:继承RetrieveModelMixin,DestroyModelMixin,GenericAPIView,有get方法获取一条,delete方法删除 RetrieveUpdateAPIView:继承RetrieveModelMixin,UpdateModelMixin,GenericAPIView,有get获取一条,put,patch修改 RetrieveUpdateDestroyAPIView:继承RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin,GenericAPIView,有get获取一条,put,patch修改,delete删除 #视图集 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
自动生成路由
# 第一步:导入routers模块 from rest_framework import routers # 第二步:有两个类,实例化得到对象 # routers.DefaultRouter 生成的路由更多 # routers.SimpleRouter router=routers.DefaultRouter() # 第三步:注册 # router.register('前缀','继承自ModelViewSet视图类','别名') router.register('books',views.BookViewSet) # 不要加斜杠了 # 第四步 # router.urls # 自动生成的路由,加入到原路由中 # print(router.urls) # urlpatterns+=router.urls
1、导入routers模块
from rest_framework import routers #SimpleRouter(一般都使用这个) #DefaultRouter(生成路由比较多)
2、实例化路由类,得到对象:
router=routers.SimpleRouter()
3、注册路由
#register('前缀‘,views文件中我们自定义的视图集函数,别名) #url(r'^book/',views.UserModelSet),前缀就等价于url的 book router.register('book',views.UserModelSet)
4、加入到原路由:
urlpatterns +=router.urls
生成接口如下:
#put、get、delete请求方法 http://127.0.0.1:8000/app04/book/pk/ #get、post请求 http://127.0.0.1:8000/app04/book/
完整代码如下:
#urls.py文件 from django.conf.urls import url from rest_framework.routers import SimpleRouter,DefaultRouter from app04 import views #实例化对象 route=SimpleRouter() #注册路由 route.register('book',views.UserModelSet,) urlpatterns = [ ] #添加路由 urlpatterns +=route.urls views.py文件 from app04.models import User,UserToken from app04.ser import UserSer,UserToken from rest_framework.viewsets import ModelViewSet # Create your views here. class UserModelSet(ModelViewSet): queryset = User.objects.all() serializer_class = UserSer
给视图类中自定义函数添加路由
1、导入一个action装饰器 ```python from rest_framework.decorators import action ``` 2、在自定义函数中添加action装饰器 ```python class UserModelSet(ModelViewSet): queryset = User.objects.all() serializer_class = UserSer ''' methods参数对应是一个列表,用来放请求方法 detail=false,接口连接如下 #^book/get_2/$ [name='book-get-1'] detail=True #^book/(?P<pk>[^/.]+)/get_2/$ [name='book-get-1'] detail:是决定是否带pk methods是请求方法 ''' @action(methods=['get'],detail=False) def get_2(self,reqeust): user=self.get_queryset()[0:2] ser=self.get_serializer(user,many=True) return Response(ser.data) ``` 最终给自定义get_2方法添加的路由如下: http://127.0.0.1:8000/app04/book/get_2/ http://127.0.0.1:8000/app04/book/pk/get_2/