1 权限,认证(了解)
1.1 权限源码
# 继承了APIView,才有的---》执行流程---》dispatch中----》三大认证
#1 APIView的dispatch的大约497行self.initial(request, *args, **kwargs)
def initial(self, request, *args, **kwargs):
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
# 2 读权限:APIView的方法self.check_permissions(request)
def check_permissions(self, request):
# 在视图层我们局部使用permission_classes = [AdminPermission]
# self.get_permissions()我们配置再视图类上permission_classes列表中的认证类,一个个的对象
# 在源码中self.get_permissions() 是 [AdminPermission(),]
for permission in self.get_permissions():
# 写的权限类,要重写has_permission方法
#permission = AdminPermission()
#所以permission是里面认证类是实例化出来的对象
if not permission.has_permission(request, self): # 权限没通过
#has_permission(self, request, view):
#permission会将自己当做第一个参数传入进去也就是self,那么后面的view对应的就是self,所以判断里面的self 是视图类的对象(BookView,PublisViwe)
self.permission_denied(
request,
# self.message 错误文字
message=getattr(permission, 'message', None),
code=getattr(permission, 'code', None)
)
# 3 读 APIView--->self.get_permissions
def get_permissions(self):
return [permission() for permission in self.permission_classes]
# 翻译:
l=[]
for permission in self.permission_classes:
l.append(permission())
return l
# 记住:
- 写的权限类,一定要写一个方法has_permission,返回True或False
- 配置再视图类上
1.3 认证源码
# 继承了APIView,才有的---》执行流程---》dispatch中----》三大认证
#1 APIView的dispatch的大约497行self.initial(request, *args, **kwargs)
def initial(self, request, *args, **kwargs):
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
# 2 self.perform_authentication(request)
def perform_authentication(self, request):
request.user # 这是个方法,包装成了数据属性
# 3 Request类的user 219 行
@property
def user(self):
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user
# 4 Request类的self._authenticate() 373 行
def _authenticate(self):
# self.authenticators 就是你写的认证类列表---》列表推导式---》[LoginAuth(),]
for authenticator in self.authenticators:
#所以authenticator = LoginAuth()是这个认证类的对象
try:
user_auth_tuple = authenticator.authenticate(self)
#这个self是request的对象,后端方法返回了user和token
except exceptions.APIException:
# 抛了异常被捕获了
if user_auth_tuple is not None:
# 如果返回了两个值,就会执行这句话
# self是Request的对象
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
# 5 Request类初始化
APIView---》dispathc的前面
# 总结:
1 认证类,必须写一个方法authenticate
2 如果认证通过,可以返回None,也可也返回两个值,但是第一个值,尽量是当前登录用户,第二个值一般放token
3 认证失败,抛异常AuthenticationFailed,继承了APIException,他能捕获
1.4 django中的翻译函数
# 只要做了国际化,会自动翻译成,当前国家的语言
from django.utils.translation import gettext_lazy as _
_('hello')
1排序
#排序----》必须是继承GenericAPIView及其子类,才能用,drf提供了要给排序类,用他的就可以了
# 如果继承APIView,不能这么用
from rest_framework.filters import OrderingFilter
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [OrderingFilter] # 排序类
# 配合一个类属性,按哪些字段可以排序
# http://127.0.0.1:8000/api/v1/books/?ordering=-price,-id
# 先按价格倒序排,价格一样,再按id倒叙排
ordering_fields = ['price','id']
2 过滤
# restful规范中
-请求地址中带过滤条件
# 带过滤的接口只有:查询所有
# 内置过滤类
#2 过滤----》必须是继承GenericAPIView及其子类,才能用,drf提供了排序类,用他的就可以了,如果继承APIView,不能这么用
from rest_framework.filters import SearchFilter
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [SearchFilter]
# 支持这种搜索
# # http://127.0.0.1:8000/api/v1/books/?search=红
# search_fields = ['name']
#http://127.0.0.1:8000/api/v1/books/?search=11 只要name或price中带11都能搜出来
search_fields = ['name','price']
# 第三方过滤类
### 2.1 第三方过滤类
# pip3 install django-filter
from django_filters.rest_framework import DjangoFilterBackend
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [DjangoFilterBackend]
# http://127.0.0.1:8000/api/v1/books/?name=红楼梦&price=45
# 按名字和价格精准匹配
filterset_fields = ['name', 'price']
#2.2 自定义过滤类 价格再100----200之间的图书
from .filter import MyFilter
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [MyFilter]
# 必须配合一个过滤类
from rest_framework import filters
from django.db.models import Q
class MyFilter(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# 返回的数据,就是过滤后的数据
# http://127.0.0.1:8000/api/v1/books/?price=44&name=红楼梦 按名字或价格
price = request.query_params.get('price')
name = request.query_params.get('name')
queryset = queryset.filter(Q(name=name) | Q(price=price))
return queryset
# 过滤和排序可以一起使用
3 排序
# restful规范中
-请求地址中带过滤条件
# 排序功能的接口:查询所有
#分页功能==-==>必须是获取所有的接口,必须继承GenericAPIView及其子类
from rest_framework.filters import OrderingFilter
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
filter_backends = [OrderingFilter] # 排序类
# 配合一个类属性,按哪些字段可以排序
# http://127.0.0.1:8000/api/v1/books/?ordering=-price,-id
# 先按价格倒序排,价格一样,再按id倒叙排
ordering_fields = ['price','id']
4 分页
# 查询所有接口,过滤和排序了,但是实际上,这个接口,都需要有分页功能
-分页的展现形式
web:下一页点解
app,小程序:下滑下一页
-接口都一样,要支持分页
# drf提供给咱们,三种分页方式
# 基本分页
# 偏移分页
# 游标分页
from .page import MyPageNumberPagination,MyLimitOffsetPagination,MyCursorPagination
# 这种方式用的多
class BookView(GenericViewSet, ListModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerialzier
# http://127.0.0.1:8000/api/v1/books/?page=2&page_size=3
# pagination_class = MyPageNumberPagination # 只能按一种方式分页,不要放到列表中了
# http://127.0.0.1:8000/api/v1/books/?limit=4&offset=3 # 从第三条数据开始,取4条
# pagination_class = MyLimitOffsetPagination # 只能按一种方式分页,不要放到列表中了
pagination_class = MyCursorPagination # 只能按一种方式分页,不要放到列表中了
#### page.py
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
## 基本分页
class MyPageNumberPagination(PageNumberPagination):
# 重写几个类属性 :4个
page_size = 2 # 每页显示的条数
page_query_param = 'page' # page=4 表示第4页
page_size_query_param = 'page_size' # page=4&page_size=5 表示查询第4页,每页显示5条
max_page_size = 5 # 每页最大显示多少条
## 偏移分页
class MyLimitOffsetPagination(LimitOffsetPagination):
# 重写几个类属性 :4个
default_limit = 2 # 每页显示多少条
limit_query_param = 'limit' # limit=3 这一页取3条
offset_query_param = 'offset' # 偏移量是多少 offset=3&limit=2 从第3条开始,拿2条
max_limit = 5 # 最多取5条
## 游标分页,只能上一页和下一页,不能直接跳到某一页,但是这个的速度快---》app上用它多
class MyCursorPagination(CursorPagination):
# 重写几个类属性 :3个
cursor_query_param = 'cursor' # 查询参数,其实用不到
page_size = 2 # 每页显示多少条
ordering = 'id' # 必须是要分页的数据表中的字段,一般按id来
作业
# 1 写查询所有出版社接口
-可以按名字或城市 模糊 匹配
-如果城市一样,可以按id倒序排列
# 2 上述接口,带分页功能
# 3 研究权限和认证源码
#### 高级###
继承APIView,实现上面1,2
1.可以按名字或城市 模糊 匹配,如果城市一样,可以按id倒序排列
2.上述接口,带分页功能(一个是基本分页,一个是游标分页)
使用方法在视图方法中pagination_class = MyPageNumberPagination
APIview中过滤排序分页的书写
过滤:
排序
分页