简单来讲,认证确定了你是谁
权限确定了你能不能访问某个接口
限制确定了你访问某个接口的最高频率
一、认证
身份验证是将传?请求与?组标识凭据(例如请求来?的?户或其签名的令牌)相关联的机制。然后权限和限制组件决定是否拒绝这个请求。认证本身不会允许或拒绝传?的请求,它只是简单识别请求携带的凭证。
REST framwork不仅自己有着开箱即用的验证方案,还允许你自己实现验证方案
1.1、自定义认证
要实现?定义的认证?案,要继承BaseAuthentication 类并且重 写.authenticate(self, request) ?法。如果认证成功,该?法应返回(user, auth) 的 ?元元组,否则返回None ,还可以抛出AuthenticationFailed 异常
在App下,创建authentications.py ,然后?定义认证类
from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app.models import Students
class appAuthentication(BaseAuthentication):
def authenticate(self, request):
token = request.query_params.get('token')
if not token:
raise AuthenticationFailed('没有 token')
username = cache.get(token)
if not username:
raise AuthenticationFailed('token 过期')
try:
student = Students.objects.filter(stu_name=username)
if student:
return student, None
else:
return None
except Exception as e:
print(e)
raise AuthenticationFailed('token 不合法')
urls.py
urlpatterns = [
path('getToken/', views.getToken.as_view(), name='getToken'),
path('testToken/',views.testToken.as_view(),name='testToken'),
]
views.py
class getToken(APIView):
def get(self, request):
username = '123'
token = token_confirm.generate_validate_token(username=username)
mycache = cache.get(token)
if mycache:
token = mycache
else:
cache.set(token, token, settings.CACHE_TIMEOUT)
return HttpResponse('http://127.0.0.1:8000/testToken?token=' + token)
class testToken(APIView):
authentication_classes = (appAuthentication,)
def get(self,request):
return HttpResponse('OK')
我们访问getToken可以得到需要验证的网址,然后这个网址登录可以看到我们登录后返回的信息,OK
我们也可以进行全局级别的认证,只是这样的话需要我们配置一下
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'App.authentications.MyAuthentication',
)
}
二、权限控制
权限控制可以限制?户对于视图的访问和对于具体数据对象的访问
在执?视图的dispatch()?法前,会先进?视图访问权限的判断
在通过get_object()获取具体对象时,会进?对象访问权限的判断
2.1、系统内置的权限
AllowAny 允许所有?户
IsAuthenticated 仅通过认证的?户
IsAdminUser 仅管理员?户
IsAuthenticatedOrReadOnly 认证的?户可以完全操作,否则只能get读取
2.2、自定义权限控制
我们自己写一个permission.py
class WomanPerssion(BasePermission):
def has_permission(self, request, view):
print(request.user)
if request.user != None:
return request.user.stu_gender == 'w'
return False
我们的视图函数只需要再加一句话
class testToken(APIView):
authentication_classes = (appAuthentication,)
permission_classes = (WomanPerssion,)
def get(self, request):
return HttpResponse('OK')
如果要进行全局的验证的话
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'App.authentications.MyAuthentication',
),
"DEFAULT_PERMISSION_CLASSES":
["app.permission.WomanPerssion",]
}
三、节流器
节流类似于权限,?于控制客户端可以对API发出的请求的速率
mythrottle.py
from rest_framework.throttling import SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
rate = '5/m'
score = 'vistor'
def get_cache_key(self, request, view):
return self.get_ident(request)
视图级别的控制
class testToken(APIView):
authentication_classes = (appAuthentication,)
permission_classes = (WomanPerssion,)
throttle_classes = (VisitThrottle,)
def get(self, request):
return HttpResponse('OK')
全局的控制
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'App.authentications.MyAuthentication',
),
"DEFAULT_PERMISSION_CLASSES":
["app.permission.WomanPerssion",],
'DEFAULT_THROTTLE_CLASSES': ['apps.mythrottle.VisitThrottle'],
'DEFAULT_THROTTLE_RATES': {
'vistor': '3/m',
'anon': '10/day',
}
}
DEFAULT_THROTTLE_RATES 可以使? second , minute , hour 或 day 来指明周期
3.1、可选限流器
3.1.1、AnonRateThrottle
限制所有匿名未认证?户,使?IP区分?户。使? DEFAULT_THROTTLE_RATES[‘anon’] 来设置频次
3.1.2、UserRateThrottle
限制认证?户,使?User id 来区分。 使? DEFAULT_THROTTLE_RATES[‘user’] 来设置频次
3.1.3、ScopedRateThrottle
限制?户对于每个视图的访问频次,使?ip或user id
eg:
class ContactListView(APIView):
throttle_scope = 'contacts'
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
四、分页Pagination
REST framework提供了分?的?持。 我们可以在配置?件中设置全局的分??式
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
4.1、自定义分页类
也可通过?定义Pagination类,来为视图添加不同分??为。在视图中通过 pagination_clas 属性来指明
注意:如果在视图内关闭分?功能,只需在视图内设置
pagination_class = None
4.2、PageNumberPagination
前端访问形式GET http://127.0.0.1:8000/studentView/?page=1
可以在?类中定义的属性: page_size 每?数? page_query_param 前端发送的?数关键字名,默认为"page" page_size_query_param 前端发送的每?数?关键字名,默认为None max_page_size 前端最多能设置的每?数量
serializer.py
from rest_framework import serializers
from app.models import Students
class studentSerializer(serializers.ModelSerializer):
class Meta:
model = Students
fields = '__all__'
models.py
class Students(models.Model):
stu_num = models.CharField(primary_key=True, max_length=8)
stu_name = models.CharField(max_length=40)
stu_gender = models.CharField(max_length=4)
stu_age = models.IntegerField()
cid = models.ForeignKey(Classes, models.DO_NOTHING, db_column='cid', blank=True, null=True)
class Meta:
managed = False
db_table = 'students'
urls.py
urlpatterns = [
path('studentView/', views.studentView.as_view(), name='studentView'),
]
views.py
class studentView(ListAPIView):
queryset = Students.objects.all()
serializer_class = studentSerializer
pagination_class = studentPagination
pagination.py
from rest_framework.pagination import PageNumberPagination
class studentPagination(PageNumberPagination):
page_size_query_param = 'page_size'
max_page_size = 1
page_size = 1
page_query_param = 'pagepage'
我们再前端访问就可以得到我们的数据了
4.3、LimitOffsetPagination
前端的访问形式GET http://127.0.0.1:8000/studentView/?limit=100&offset=400
可以在?类中定义的属性:
default_limit 默认限制,默认值与 PAGE_SIZE 设置?直
limit_query_param limit参数名,默认'limit'
offset_query_param offset参数名,默认'offset'
max_limit 最?limit限制,默认None
他的设置方法和前面的一致
五、过滤
对于列表数据可能需要根据字段进?过滤,我们可以通过添加django-fitlter扩展来增强?持。官?地址:https://django-filter.readthedocs.io/en/master/index.html
5.1、安装
pip install django-filter
5.2、配置
settings.py
INSTALLED_APPS = [
'django_filters',
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
5.3、视图设置
class studentView(ListAPIView):
queryset = Students.objects.all()
serializer_class = studentSerializer
filter_fields = ('stu_name', 'stu_gender')
其他的和上面的保持一致,我们访问下面这个地址
GET http://127.0.0.1:8000/studentView/?stu_gender=w
5.4、自定义过滤类
customfilter.py
import django_filters
from django_filters import rest_framework as filters
from app.models import Students
class studentsFilters(django_filters.FilterSet):
class Meta:
min_read = filters.NumberFilter(field_name="bread", lookup_expr='gte')
ax_read = filters.NumberFilter(field_name="bread", lookup_expr='lte')
model = Students
fields = {
'stu_age': ['icontains'],
}
views.py
class studentView(ListAPIView):
queryset = Students.objects.all()
serializer_class = studentSerializer
filter_class = studentsFilters
- field_name 数据库中字段名
- lookup_expr 操作(和django的orm中运算符?样) 关系运算符:gte(>=) 、gt(>)、 lte(<=)、 lt(<) 字符串; icontains(忽略??写,包含)
- model指定模型
- fields可以指定过滤字段
访问测试:
http://127.0.0.1:8000/studentView/?stu_gender=w
http://127.0.0.1:8000/studentView/?minage=0&maxage=2
这个其实并不重要,我们可以直接数据查询返回
六、自动生成接口文档
6.1、安装
pip install coreapi
6.2、配置
settings.py
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
}
6.3、设置接??档访问路径
在总路由中添加接??档路径。
?档路由对应的视图配置为 rest_framework.documentation.include_docs_urls ,
参数 title 为接??档?站的标题
6.4、文档描述说明定义
6.4.1、单一方法视图
单??法的视图,可直接使?类视图的?档字符串,如
class BookListView(generics.ListAPIView):
"""
返回所有图书信息.
"""
6.4.1、多个方法视图
class BookListCreateView(generics.ListCreateAPIView):
"""
get:
返回所有图书信息.
post:
新建图书.
"""
6.4.3、视图集
对于视图集ViewSet,仍在类视图的?档字符串中分开定义,但是应使?action 名称区分,
class BookInfoViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin, GenericViewSet):
"""
list:
返回图书列表数据
retrieve:
返回图书详情数据
latest:
返回最新的图书数据
read:
修改图书的阅读量
"""
6.4.4、网址访问
http://127.0.0.1:8000/docs/
|