昨日回顾
-APIView---》继承自View
-GenicAPIView---》APIView,做了一些扩展:
-queryset = None
-serializer_class = None
-get_queryset() 经常用
-get_serializer() 经常用
-get_serializer_class() 内部来用,外部会重写
-get_object() 经常用,获取一条数据(pk传过来)
-源码解析
queryset = self.filter_queryset(self.get_queryset())
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs)
self.check_object_permissions(self.request, obj)
return obj
-5 个视图扩展类(继承了object),每个里面写了一个方法(ListModelMixin:list方法)
ListModelMixin,
CreateModelMixin,
UpdateModelMixin,
DestroyModelMixin,
RetrieveModelMixin
-GenericAPIView的视图子类,9个,继承了GenicAPIView+一个或者两个或者三个视图扩展类
CreateAPIView,
ListAPIView,
UpdateAPIView,
RetrieveAPIView,
DestroyAPIView,
ListCreateAPIView,
RetrieveUpdateDestroyAPIView,
RetrieveDestroyAPIView,
RetrieveUpdateAPIView
-视图集:ModelViewSet,ReadOnlyModelViewSet:继承了上面一堆(5个视图扩展和GenicAPIView)+自己写了一个ViewSetMixin(as_view方法),只要继承它的,路由得写成{‘get’:‘自己定义的方法’}
-ViewSet=ViewSetMixin, views.APIView :ViewSetMixin要放在前面
-GenericViewSet=ViewSetMixin+GenicAPIView
-ViewSetMixin(as_view方法)
-ViewSetMixin+APIView=ViewSet
-ViewSetMixin+GenicAPIView=GenericViewSet
今日内容
1 路由
path('books4/', views.Book4View.as_view()),
re_path('books4/(?P<pk>d+)', views.Book4DetailView.as_view()),
path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})),
re_path('books5/(?P<pk>d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),
-urls.py
from rest_framework import routers
router=routers.DefaultRouter()
router.register('books',views.BookViewSet)
'''
-views.py
from rest_framework.viewsets import ModelViewSet
from app01.models import Book
from app01.ser import BookSerializer
class BookViewSet(ModelViewSet):
queryset =Book.objects
serializer_class = BookSerializer
1.1 action的使用
class BookViewSet(ModelViewSet):
queryset =Book.objects.all()
serializer_class = BookSerializer
@action(methods=['GET','POST'],detail=True)
def get_1(self,request,pk):
print(pk)
book=self.get_queryset()[:2]
ser=self.get_serializer(book,many=True)
return Response(ser.data)
2 认证
2.1 认证的写法
1 写一个类,继承BaseAuthentication,重写authenticate,认证的逻辑写在里面,认证通过,返回两个值,一个值最终给了Requet对象的user,认证失败,抛异常:APIException或者AuthenticationFailed(这个是前者的子类)
2 全局使用,局部使用
2.2 认证的源码分析
def _authenticate(self):
for authenticator in self.authenticators:
try:
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
2.3 认证组件的使用
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01.models import UserToken
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
token=request.GET.get('token')
if token:
user_token=UserToken.objects.filter(token=token).first()
if user_token:
return user_token.user,token
else:
raise AuthenticationFailed('认证失败')
else:
raise AuthenticationFailed('请求地址中需要携带token')
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",]
}
authentication_classes=[MyAuthentication]
authentication_classes=[]
作业
1 继承ModelViewSet,获取所有的,只获取前10条
2 登陆接口,查询图书接口,必须登录后才能查看,token信息放在头里(认证组件),全局使用,局部禁用(login禁用)
3 使用simplerouter自动生成路由