首先看看该框架的功能: 1、 解析器 2、 序列化组件 3、 APIView 4、 通用视图(mixin) 5、 分页组件 6、 响应器 7、 路由注册器 8、 认证组件 9、 权限组件 10、 限流
REST framework 包含许多内置的解析器类,允许接受各种媒体类型(media types)的请求。还支持自定义解析器,这使你可以灵活地设计 API 接受的媒体类型。
在settings文件中配置文件:
REST_FRAMEWORK={ 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', ), }如上,可以使用 DEFAULT_PARSER_CLASSES 设置默认的全局解析器。如上,设置将带有JSON 、表单数据内容的请求,而不是默认的 JSON。详细解释请参照rest_framework文档。
除了默认设置外,还可以对单个视图或视图集设置,详细解释请参照rest_framework文档。
序列化器允许将诸如查询集和模型实例之类的复杂数据转换为原生 Python 数据类型,然后可以将它们轻松地呈现为 JSON ,XML 或其他内容类型。序列化器还提供反序列化,在首次验证传入数据之后,可以将解析的数据转换回复杂类型。
因此,这些是有代码量的,rest_framework对这部分做了优化,引入了Serializers。在实际使用过程中,我们会在应用里,添加serializes.py文件,来引入序列化器。
在serializes.py添加:
from .models import Article, Reporter, testmysql from rest_framework import serializers from rest_framework import validators from rest_framework.validators import UniqueValidator class testmysqlSerializer(serializers.Serializer): student_name = serializers.CharField(max_length=16, validators=[validators.UniqueValidator(queryset=testmysql.objects.all(), message='数据已存在')]) course_name = serializers.CharField(max_length=16)REST framework 提供了一个 APIView 类,它继承于 Django 的 View 类。
APIView 类与不同的 View 类有所不同: 1、传递给处理方法的 request 对象是 REST framework 的 Request 实例,而不是Django 的 HttpRequest 实例。 2、处理方法可能返回 REST framework 的 Response ,而不是 Django 的 HttpResponse。该视图将管理内容协商,并在响应中设置正确的渲染器。 3、任何 APIException 异常都会被捕获并进行适当的响应。 传入的请求会进行认证,在请求分派给处理方法之前将进行适当的权限检查(允许或限制)。
像往常一样,使用 APIView 类与使用常规 View 类非常相似,传入的请求被分派到适当的处理方法,如 .get() 或 .post() 。此外,可以在类上设置许多属性(AOP)。
在views.py添加:
from django.shortcuts import render from django.http import JsonResponse import json from firstapp.models import testmysql from .serializers import ArticleSerializer, testmysqlSerializer from rest_framework.views import APIView # Create your views here. class student(APIView): def post(self, request): response = {} # 响应 if request.method == "POST": req = json.loads(request.body) print(req) else: response["msg"] = "请求方法错误" response["code"] = 400 return JsonResponse(response) a = testmysqlSerializer(data=req) if a.is_valid(): testmysql.objects.create(**a.validated_data) else: return JsonResponse(a.errors) response["错误码"] = 200 return JsonResponse(response)在urls.py添加:
urlpatterns = [ path('student/', student.as_view()) ]如上,是apiView的应用方式,代码不用运行,理解即可。
基于类的视图的一个主要优点是它们允许你编写可重复使用的行为。 REST framework 通过提供大通用视图,来提供常用模式。我们需要充分利用这一点。
REST framework 提供的通用视图允许您快速构建紧密映射到数据库模型的 API 视图。
如果通用视图不符合需求,可以使用常规的 APIView 类,或者利用 mixin 特性和基类组合出可重用的视图。
mixin可以大大简化代码量,当然,这种方式写出来的接口,灵活度就不高了。
1、mixin相关组件的使用
在urls.py添加:
urlpatterns = [ path('test01/', test01_student.as_view()), path('test02/<int:pk>/', test02_student.as_view()) ]在views.py中添加:
class test01_student(ListModelMixin, CreateModelMixin, GenericAPIView): queryset = testmysql.objects.all() serializer_class = testmysqlSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class test02_student(UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, GenericAPIView): queryset = testmysql.objects.all() serializer_class = testmysqlSerializer def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs)如上,通过视图写出的接口相当简洁。
2、generics的使用
在views.py中添加:
from rest_framework import generics class test03_student(generics.ListCreateAPIView): queryset = testmysql.objects.all() serializer_class = testmysqlSerializer class test04_student(generics.RetrieveUpdateDestroyAPIView): queryset = testmysql.objects.all() serializer_class = testmysqlSerializer如上,通过该组件,直接实现了1中的接口功能。
3、ModelViewSet使用
在urls.py中添加:
urlpatterns = [ path('test05/', test05_student.as_view({"get":"list","post":"create"})), path('test05/<int:pk>/', test05_student.as_view({"get":"retrieve","delete":"destroy","put":"update"})), ]在views.py中添加:
from rest_framework.viewsets import ModelViewSet class test05_student(ModelViewSet): queryset = testmysql.objects.all() serializer_class = testmysqlSerializer详细解释请参照rest_framework文档。
REST framework 包含对可定制分页样式的支持。这使你可以将较大的结果集分成单独的数据页面。 分页 API 支持: 1、以分页链接的形式作为响应内容的一部分。 2、以分页链接的形式包含在响应的 header 中,如 Content-Range 或 Link .
内置的样式目前是以分页链接的形式作为响应内容的一部分。使用可浏览的 API 时,此样式更易于访问。
分页仅在你使用通用视图或视图集时自动执行。如果你使用的是常规 APIView ,则需要自己调用分页 API 以确保返回分页响应。示例请参阅 mixins.ListModelMixin 和generics.GenericAPIView 类的源代码。
可以通过将分页类设置为 None ,关闭分页。
1、PageNumberPagination (1) APIView
class test07_student(APIView): class Pages(PageNumberPagination): page_size = 10 pagination_class = Pages def get(self, request): class Pages(PageNumberPagination): page_query_param = "page" # 设置url参数page page_size_query_param = "size" # 设置url参数size page_size = 10 # 默认显示 book_obj = testmysql.objects.all() P = Pages() paged_book_list = P.paginate_queryset(book_obj, request) T = testmysqlSerializer(paged_book_list, many=True) data = T.data # 序列化接口 return Response(data)(2)ModelViewSet
class test06_student(ModelViewSet): class Pages(PageNumberPagination): page_size = 10 pagination_class = Pages queryset = testmysql.objects.all() serializer_class = testmysqlSerializer2、LimitOffsetPagination (1)ModelViewSet
class test08_student(ModelViewSet): class Pages(LimitOffsetPagination): default_limit = 10 # 每页显示 offset_query_param = 'offset' # 当前所在的位置 limit_query_param = 'limit' # 往后取几条 pagination_class = Pages queryset = testmysql.objects.all() serializer_class = testmysqlSerializer更多分页组件,请查看rest_framework官方文档。
你不太可能希望为 REST framework 提供自定义内容协商方案,但如果需要,你可以这样做。要实现自定义内容协商方案,请覆盖 BaseContentNegotiation 。 REST framework 的内容协商类处理选择适当的请求解析器和适当的响应渲染器,因此你应该实现.select_parser(request, parsers) 和 .select_renderer(request, renderers,format_suffix) 方法。 select_parser() 方法应从可用解析器列表中返回一个解析器实例,如果没有任何解析器可以处理传入请求,则返回 None 。 select_renderer() 方法应该返回(渲染器实例,媒体类型)的二元组,或引发NotAcceptable 异常。
解析器parsers在Settings文件中配置,响应器renderer也在该文件配置:
REST_FRAMEWORK={ 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser', ), 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', ), }与解析器一样,响应器可以根据客户端的请求,来返回格式,如上面的JSON格式,当然,更多内容,请查看相关文档。
因为我们使用的是ViewSet类而不是View类,如ModelViewSet。所以我们实际上不需要自己设计URL conf。可以使用Router类自动处理将资源连接到视图和url中的约定。我们所需要做的就是向路由器注册适当的视图集,然后让它来完成剩下的工作。
from django.urls import path, include from rest_framework.routers import DefaultRouter from firstapp.views import add_data, query_data, update_data, delete_data, student, \ test01_student, test02_student, test03_student, test04_student, test05_student, \ test06_student, test07_student, test08_student # Create a router and register our viewsets with it. router = DefaultRouter() router.register(r'test09', test08_student) # The API URLs are now determined automatically by the router. urlpatterns = [ path('', include(router.urls)), path('firstapp/', add_data), path('firstapp/<int:pk>/', query_data), path('firstapp/update/<int:pk>/', update_data), path('firstapp/delete/<int:pk>/', delete_data), path('student/', student.as_view()), path('test01/', test01_student.as_view()), path('test02/<int:pk>/', test02_student.as_view()), path('test03/', test03_student.as_view()), path('test04/', test04_student.as_view()), path('test05/', test05_student.as_view({"get":"list","post":"create"})), path('test05/<int:pk>/', test05_student.as_view({"get":"retrieve","delete":"destroy","put":"update"})), path('test06/', test06_student.as_view({"get": "list", "post": "create"})), path('test06/<int:pk>/', test06_student.as_view({"get": "retrieve", "delete": "destroy", "put": "update"})), path('test07/', test07_student.as_view()), path('test07/<int:pk>/', test07_student.as_view()), path('test08/', test08_student.as_view({"get": "list", "post": "create"})), path('test08/<int:pk>/', test08_student.as_view({"get": "retrieve", "delete": "destroy", "put": "update"})), ]如上,通过DefaultRouter()可以自动生成路由,更多路由类,请查看官方文档。
身份验证是将传入请求与一组识别凭证(例如请求的用户或其签名的令牌)相关联的机制。然后,权限 和限制策略可以使用这些凭据来确定请求是否应该被允许。
REST framework 提供了许多开箱即用的身份验证方案,同时也允许你实施自定义方案。
身份验证始终在视图的开始处运行,在执行权限和限制检查之前,在允许继续执行任何其他代码之前。 request.user 属性通常会设置为 contrib.auth 包的 User 类的一个实例。
request.auth 属性用于其他身份验证信息,例如,它可以用来表示请求已签名的身份验证令牌。
注意: 不要忘记, 身份验证本身不会(允许或不允许)传入的请求,它只是标识请求的凭据。
默认的认证方案可以在settings.py文件中使用DEFAULT_AUTHENTICATION_CLASSES全局设置。例如:
REST_FRAMEWORK={ 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser', ), 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', ), 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.TokenAuthentication', ), }如上是3种认证方案:
BasicAuthentication:该认证方案使用 HTTP Basic Authentication,并根据用户的用户名和密码进行签名,通常只适用于测试,如果需要自定义认证,需要继承该类。
TokenAuthentication:此认证方案使用简单的基于令牌的 HTTP 认证方案。令牌身份验证适用于 client-server 架构,例如本机桌面和移动客户端。
SessionAuthentication:此认证方案使用 Django 的默认 session 后端进行认证。Session 身份验证适用于与您的网站在同一会话环境中运行的 AJAX 客户端。
确保在更改设置后运行 manage.py migrate ,这样才生效。rest_framework.authtoken 应用程序提供 Django 数据库迁移。
认证流程应该是前端进行登录,后端生成认证信息,后续的接口,都需要通过认证信息进行认证,这里采用自定义Token:
注册rest_framework.authtoken:
INSTALLED_APPS = [ 'rest_framework.authtoken', ]自定义认证类:
class auth(BaseAuthentication): def authenticate(self, request): token = request.query_params.get("token") usertoken_obj = UserToken.objects.filter(token=token).first() if usertoken_obj: return usertoken_obj.user, usertoken_obj.token else: raise AuthenticationFailed("Token认证失败")在认证的视图里添加自定义认证类:
class test10_student(APIView): authentication_classes = [auth, ] # permission_classes = [IsAuthenticated] class Pages(PageNumberPagination): page_size = 10 pagination_class = Pages def get(self, request): class Pages(PageNumberPagination): page_query_param = "page" # 设置url参数page page_size_query_param = "size" # 设置url参数size page_size = 10 # 默认显示 book_obj = testmysql.objects.all() P = Pages() # 分页 paged_book_list = P.paginate_queryset(book_obj, request) T = testmysqlSerializer(paged_book_list, many=True) data = T.data # 序列化接口 return Response(data)或者直接设置全局认证,需要在REST_FRAMEWORK注册自定义认证类。
执行迁移:
python manage.py makemigrations python manage.py migrate与 authentication 和 throttling 一起,permission 决定是应该接受还是拒绝访问请求。
权限检查总是在视图的最开始处运行,在任何其他代码被允许进行之前。权限检查通常会使用request.user 和 request.auth 属性中的认证信息来确定是否允许传入请求。
权限用于授予或拒绝不同类别的用户访问 API 的不同部分。
最简单的权限是允许通过身份验证的用户访问,并拒绝未经身份验证的用户访问。这对应于 REST framework 中的 IsAuthenticated 类。
稍微宽松的权限会允许通过身份验证的用户完全访问,而未通过身份验证的用户只能进行只读访问。这对应于 REST framework 中的 IsAuthenticatedOrReadOnly 类。
自定义的权限可以使用BasePermission,用法跟认证组件类似,可查阅官方文档。
限流与权限类似,因为它确定是否应该授权请求。 限流阀指示临时状态,并用于控制客户端可以对API进行的请求速率。
与权限一样,可能会使用多种限流方式。你的 API 可能对未经身份验证的请求进行限流,对经过身份验证的请求限流较少。
如果你需要对 API 的不同部分使用不同的限流策略,由于某些服务特别占用资源,你可能想要使用同时有多种限流策略的另一种方案。
如果你想要同时实现爆发限流率和持续限流率,也可以使用多个限流阀。例如,你可能希望将用户限制为每分钟最多 60 个请求,并且每天最多 1000 个请求。
限流阀不一定只限制请求频率。例如,存储服务可能还需要对带宽进行限制,而付费数据服务可能希望对正在访问的某些记录进行限制。
使用方式可查阅官方文档,下面是一个例子:
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ], 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', 'user': '1000/day' } }