【Django_rest_framework/drf详解】
Django\DRF
1.Django的CBV
1.1 CBV源码分析
-
CBV是基于反射实现的
-
请求进来执行
as_view()函数的dispatch()方法,如果自己在views中定义了自己的dispatch()就会执行自己的dispatch()# 试图函数/api Class StudentsView(View): def dispatch(self,request,*args,**kwargs): func = getattr(self.request.method.lower()) ret = func(request,*args,**kwargs) return ret def get(self,request,*args,**kwargs): return HttpResponse('GET') def post(self,request,*args,**kwargs): return HttpResponse('POST') def put(self,request,*args,**kwargs): return HttpResponse('PUT') def delete(self,request,*args,**kwargs): return HttpResponse('DELETE') -
但其实这个dispatch在父类的view中已经实现了
# view源码 def dispatch(self,request,*args,**kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, equest.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request,*args,**kwargs) -
CBV定义:CBV是基于反射实现的根据请求方式不同,执行不同方法。
-
CBV原理:
-
路由:
-
url----->view函数 ----->dispatch方法(反射执行其他方法:GET/POST/PUT/DELETE......) -
请求过程如下图
-
-
-
对
dispatch()进一步封装:# 视图函数/api class MyBaseView(object): def dispatch(self,request,*args,**kwargs): print("before request") ret = super(MyBaseView,self).dispatch(request,*args,**kwargs) print("after request") return ret Class TeachersView(MyBaseView,View):# 继承自己的类实现类似于装饰器的功能 def get(self,request,*args,**kwargs): return HttpResponse('GET') def post(self,request,*args,**kwargs): return HttpResponse('POST') def put(self,request,*args,**kwargs): return HttpResponse('PUT') def delete(self,request,*args,**kwargs): return HttpResponse('DELETE') Class StudentsView(MyBaseView,View):# 继承自己的类实现类似于装饰器的功能 def dispatch(self,request,*args,**kwargs): func = getattr(self.request.method.lower()) ret = func(request,*args,**kwargs) return ret def get(self,request,*args,**kwargs): return HttpResponse('GET') def post(self,request,*args,**kwargs): return HttpResponse('POST') def put(self,request,*args,**kwargs): return HttpResponse('PUT') def delete(self,request,*args,**kwargs): return HttpResponse('DELETE')
2.Django的中间件
2.1 Django的中间件有哪些
- process_request
- process_view
- process_response
- process_exception
- process_render_template
2.2 用中间件做过可以做哪些
- 权限验证
- 登录验证
- Django的csrf是如何实现的
- 基于中间件的process_view方法
- 免除csrf认证(@csrf_exempt)
- 去请求体或者cookie中获取token
- 基于中间件的process_view方法
2.3 使用方法
-
settings中middleware-csrf表示全局使用csrf_token
-
免除csrf-
@csrf_exempt -
增加csrf-
@csrf_protect -
CBV加csrf装饰器
-
类的dispatch方法用@method_decorator(csrf_exempt)
Class TeachersView(View): @method_decorator(csrf_exempt) def dispatch(self,request,*args,**kwargs): print("before request") ret = super(MyBaseView,self).dispatch(request,*args,**kwargs) print("after request") return ret def get(self,request,*args,**kwargs): return HttpResponse('GET') def post(self,request,*args,**kwargs): return HttpResponse('POST') def put(self,request,*args,**kwargs): return HttpResponse('PUT') def delete(self,request,*args,**kwargs): return HttpResponse('DELETE') -
类上面用@method_decorator(csrf_exempt)
@method_decorator(csrf_exempt) Class TeachersView(View): def dispatch(self,request,*args,**kwargs): print("before request") ret = super(MyBaseView,self).dispatch(request,*args,**kwargs) print("after request") return ret def get(self,request,*args,**kwargs): return HttpResponse('GET') def post(self,request,*args,**kwargs): return HttpResponse('POST') def put(self,request,*args,**kwargs): return HttpResponse('PUT') def delete(self,request,*args,**kwargs): return HttpResponse('DELETE')
-
3.DRF认证
问题:登录之后才能访问
3.1 基本使用
-
梳理
-
使用
- 创建类:继承
BaseAuthentication;重写authenticate方法
# auth.py from api.user import models from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication class Authticatition(BaseAuthentication): def authenticate(self, request): token = request._request.GET.get("token") token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed("用户认证失败") def authenticate_header(self, request): pass- 返回值:
None:下一步来认证raise exceptionrequest.user、request.auth
- 局部使用:类中加静态字段
# OrderView.py from api.utils.auth import Authticatition class OrderView(APIView): authentication_classes = [Authticatition, ] def get(self, request, *args, **kwargs): return HttpResponse("get") def post(self, request, *args, **kwargs): return HttpResponse("post") def put(self, request, *args, **kwargs): return HttpResponse("put") def delete(self, request, *args, **kwargs): return HttpResponse("delete")- 全局使用
# settings.py REST_FRAMEWORK = { # 全局认证类 "DEFAULT_AUTHENTICATION_CLASSES": ['api.utils.auth.Authticatition', ], # "UNAUTHENTICATED_USER":lambda:"匿名用户", "UNAUTHENTICATED_USER": None, # 匿名用户 "UNAUTHENTICATED_TOKEN": None, # 匿名用户 } - 创建类:继承
-
3.2 源码流程
- dispatch
-
request封装
- 获取定义的所有认证类(全局,局部使用) 通过列表生成式创建对象
-
initial
- perform_authtication
- request.user(内部循环)
- perform_authtication
-
4.DRF权限
4.1 基本使用
-
梳理
-
使用
-
创建类:继承
BasePermission;重写has_permission和has_object_permission方法# utils.permission.py from rest_framework.permissions import BasePermission class MyPermission(BasePermission): message = "只有vip才能访问" def has_permission(self, request, view): """做具体的权限内容""" if request.user.user_type != 3: return False return True def has_object_permission(self, request, view, obj): return True
-
- message:接口看到的信息 - 返回值 - True:有权限 - False:无权限 - 局部使用:类中加静态字段 ```python # OrderView.py class OrderView(APIView): authentication_classes = [Authticatition, ] # 登陆状态 局部用全局不同 permission_classes = [MyPermission, ] # 权限 局部用全局不同 def get(self, request, *args, **kwargs): res = API_TEMPLATE.copy() data = Order.objects.all().values() res.update(code=HttpCode.ok.value[0], msg=HttpCode.ok.value[1], data=str(data)) return JsonResponse(res)-
全局使用
# settings.py REST_FRAMEWORK = { # 认证相关 "DEFAULT_AUTHENTICATION_CLASSES": ['api.utils.auth.Authticatition', ], # "UNAUTHENTICATED_USER":lambda:"匿名用户", "UNAUTHENTICATED_USER": None, # 匿名用户 "UNAUTHENTICATED_TOKEN": None, # 匿名用户 # 权限相关 "DEFAULT_PERMISSION_CLASSES":['api.utils.permission.MyPermission',] } -
如果全局使用局部不用
class OrderView(APIView): permission_classes = [] # 权限 局部用全局不同 # settings.py REST_FRAMEWORK = { # 认证相关 "DEFAULT_AUTHENTICATION_CLASSES": ['api.utils.auth.Authticatition', ], # "UNAUTHENTICATED_USER":lambda:"匿名用户", "UNAUTHENTICATED_USER": None, # 匿名用户 "UNAUTHENTICATED_TOKEN": None, # 匿名用户 # 权限相关 "DEFAULT_PERMISSION_CLASSES":['api.utils.permission.MyPermission',] }
-
4.2 源码流程
-
dispatch
- request封装
- 获取定义的所有认证类(全局,局部使用) 通过列表生成式创建对象
-
initial中封装了权限
self.check_permissions(request)for permission in self.get_permissions():- 循环遍历permission
- get_permissions() 返回一个列表
4.3 内置权限
from rest_framework.permissions import BasePermission
# 继承这个BasePermission
# BasePermission
class MyPermission(BasePermission):
pass
class BasePermission(metaclass=BasePermissionMetaclass):
"""
A base class from which all permission classes should inherit.
"""
def has_permission(self, request, view):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True
5.DRF节流
5.1 基本使用
-
梳理
-
使用
-
创建类:继承
BaseThrottle;重写allow_request和wait方法# 自己实现的 from rest_framework.throttling import BaseThrottle import time VISIT_RECORD = {} # 可以用缓存代替 class VisitThrottle(BaseThrottle): def __init__(self): self.history = None def allow_request(self, request, view): """Return `True` 可以访问, `False` 不能访问. """ # 获取用户ip remote_addr = request.META.get('REMOTE_ADDR') ctime = time.time() # 判断ip是不是再dict中 if remote_addr not in VISIT_RECORD: VISIT_RECORD[remote_addr] = ctime return True history = VISIT_RECORD.get(remote_addr) self.history = history while history and history[-1] < ctime - 60: history.pop() if len(history) < 3: history.insert(0, remote_addr) return True return False def wait(self): """再等多少秒访问""" ctime = time.time() return 60 - (ctime - self.history[-1]) -
全局使用
# settings.py REST_FRAMEWORK = { # 认证相关 "DEFAULT_AUTHENTICATION_CLASSES": ['api.utils.auth.Authticatition', ], # "UNAUTHENTICATED_USER":lambda:"匿名用户", "UNAUTHENTICATED_USER": None, # 匿名用户 "UNAUTHENTICATED_TOKEN": None, # 匿名用户 # 权限相关 "DEFAULT_THROTTLE_CLASSES": ['api.utils.throttle.VisitThrottle', ] # 节流相关 "DEFAULT_PERMISSION_CLASSES": ['api.utils.permission.MyPermission', ] } -
局部使用
class OrderView(APIView): authentication_classes = [Authticatition, ] # 登陆状态 局部用全局不同 permission_classes = [MyPermission, ] # 权限 局部用全局不同 throttle_classes = [VisitThrottle, ] # 节流 def get(self, request, *args, **kwargs): res = API_TEMPLATE.copy() data = Order.objects.all().values() res.update(code=HttpCode.ok.value[0], msg=HttpCode.ok.value[1], data=str(data)) return JsonResponse(res)
-
-
5.2 源码流程
和权限相似
5.3 内置权限
-
SimpleRateThrottlefrom rest_framework.throttling import BaseThrottle import time VISIT_RECORD = {} # 可以用缓存代替 class VisitThrottle(SimpleRateThrottle): scop = "luffy"
6.DRF版本
6.1 url的GET传参数
-
url的GET传参数
127.0.0.0:8000/api/user?version=1 -
url中的参数
# 路由中要匹配 127.0.0.0:8000/api/v1/user?version=1 -
基本使用
class QueryParameterVersioning(BaseVersioning): """ GET /something/?version=0.1 HTTP/1.1 Host: example.com Accept: application/json """ invalid_version_message = _('Invalid version in query parameter.') def determine_version(self, request, *args, **kwargs): version = request.query_params.get(self.version_param, self.default_version) if not self.is_allowed_version(version): raise exceptions.NotFound(self.invalid_version_message) return version def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra): url = super().reverse( viewname, args, kwargs, request, format, **extra ) if request.version is not None: return replace_query_param(url, self.version_param, request.version) return urlfrom rest_framework.versioning import QueryParameterVersioning class AuthView(APIView): versioning_class = QueryParameterVersioning # url传参获取 # versioning_class = URLPathVersioning # url传参获取 def post(self, request, *args, **kwargs): print(request.version) return JsonResponse(res) -
全局使用
REST_FRAMEWORK = { # 版本 QueryParameterVersioning的配置 # "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.QueryParameterVersioning", # 处理版本的类 "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.URLPathVersioning", # 处理版本的类 "DEFAULT_VERSION": "v1", # 默认的版本 "ALLOWED_VERSIONS": ["v1", "v2"], # 允许的版本 "VERSION_PARAM": "version", # url中的key }
7.DRF解析器
7.1 Django的request
"""
如果前端以 json 格式传输数据,后端直接 request.data 就是一个字典格式的数据
如果前端以 form 格式传输数据,后端直接 request.data.dict() 就是一个字典格式的数据
"""
-
django想通过
request.POST获取到值有两个条件-
请求头必须是:
Content-Type:application/x-www-form-urlencoded -
数据格式:
name=jack&age=18 -
form表单提交默认就是Content-Type:application/x-www-form-urlencoded<form> ... </form> -
ajax提交指认header
$.ajax({ url:... type:post, headers:{'Content-Type:application/x-www-form-urlencoded'} data:{name:jack,age:18} })
-
7.2 rest_framework解析器
-
rest_framework解析器,通过设置
JSONParser,FormParser可以使用request.data获取到值from rest_framework.parsers import JSONParser, FormParser class DjangoView(APIView): # JSONParser处理Content-Type:application/json # FormParser处理Content-Type:application/x-www-form-urlencoded parser_classes = [JSONParser, FormParser] # 允许用户发json数据 def post(self, request, *args, **kwargs): """ 1.获取用户请求 2.获取用户请求体 3.获取用户请求头 和 parser_classes中支持的请求头进行比较 4.JSONParser对象去请求体 5.request.data """ print(request.data) return HttpResponse("django") def get(self, request, *args, **kwargs): return HttpResponse("django") -
解析器的局部配置
from rest_framework.parsers import JSONParser, FormParser class DjangoView(APIView): parser_classes = [JSONParser, FormParser] # 允许用户发json数据 def post(self, request, *args, **kwargs): return HttpResponse("django") -
解析器的全局设置
REST_FRAMEWORK = { # 解析器 "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser", "rest_framework.parsers.FormParser"] } -
除了
JSONParser,FormParser还包括其他很多Parser -
总结
- 解析器一般做全局配置
- 部分要用到特殊的局部配置,比如上传文件
7.3 源码流程
- dispatch:request封装了parser
- request.data获取值
8.DRF序列化器
8.1 做序列化queryset
8.1 基本使用
-
django处理Queryset
# django处理Queryset from api.user.models import Role import json class RolesView(APIView): def get(self, request, *args, **kwargs): res = API_TEMPLATE.copy() data = Role.objects.all().values('id', 'title') roles = list(data) ret = json.dumps(roles, ensure_ascii=False) res.update(code=HttpCode.ok.value[0], msg=HttpCode.ok.value[1], data=ret) return JsonResponse(res) -
DRF处理Queryset
# drf处理Queryset from api.user.models import Role from rest_framework import serializers import json class RolesSerializers(serializers.Serializer): """定义一个序列化类""" id = serializers.IntegerField() title = serializers.CharField() class RolesView(APIView): def get(self, request, *args, **kwargs): res = API_TEMPLATE.copy() # # 多个数据many=True # roles = Role.objects.all() # ser = RolesSerializers(instance=roles, many=True) # ret = json.dumps(ser.data, ensure_ascii=False) # 一个数据many=False roles = Role.objects.first() ser = RolesSerializers(instance=roles, many=False) ret = json.dumps(ser.data, ensure_ascii=False) res.update(code=HttpCode.ok.value[0], msg=HttpCode.ok.value[1], data=ret) return JsonResponse(res) -
枚举类
# source="get_字段名_display" user_type = serializers.CharField(source="get_user_type_display") -
一对一
# 外键的处理 group = serializers.CharField(source="group.title") -
多对多
# 多对多的显示 SerializerMethodField 自定义显示 get_rls() rls = serializers.SerializerMethodField() def get_rls(self, row): # get_+字段名称 role_obj_list = row.roles.all() ret = [] for item in role_obj_list: ret.append({"id": item.id, "title": item.title}) return ret
8.2 总结:
-
写类
# 定制字段 功能更加丰富 class UserInfoSerializer(serializers.Serializer): # 枚举choices的处理 # user_type = serializers.CharField(source="user_type") # source会关联查询数据 user_type = serializers.CharField(source="get_user_type_display") username = serializers.CharField() password = serializers.CharField() # 外键的处理 group = serializers.CharField(source="group.title") # 多对多的显示 SerializerMethodField 自定义显示 get_rls() rls = serializers.SerializerMethodField() def get_rls(self, row): # get_+字段名称 role_obj_list = row.roles.all() ret = [] for item in role_obj_list: ret.append({"id": item.id, "title": item.title}) return ret# 全部匹配 比较简单 功能不全 class UserInfoSerializer2(serializers.Serializer): # 枚举choices的处理 class meta: model = UserInfo fields = "__all__" # 显示全部 # fields = ["id","username","password","oooo"] -
字段
# source="get_字段名_display" user_type = serializers.CharField(source="get_user_type_display") # 外键的处理 group = serializers.CharField(source="group.title") # 多对多的显示 SerializerMethodField 自定义显示 get_rls() rls = serializers.SerializerMethodField() def get_rls(self, row): # get_+字段名称 role_obj_list = row.roles.all() ret = [] for item in role_obj_list: ret.append({"id": item.id, "title": item.title}) return ret -
全部代码
from api.user.models import UserInfo # 定制字段 功能更加丰富 class UserInfoSerializer(serializers.Serializer): # 枚举choices的处理 # user_type = serializers.CharField(source="user_type") # source会关联查询数据 user_type = serializers.CharField(source="get_user_type_display") username = serializers.CharField() password = serializers.CharField() # 外键的处理 group = serializers.CharField(source="group.title") # 多对多的显示 SerializerMethodField 自定义显示 get_rls() rls = serializers.SerializerMethodField() def get_rls(self, row): # get_+字段名称 role_obj_list = row.roles.all() ret = [] for item in role_obj_list: ret.append({"id": item.id, "title": item.title}) return ret # 全部匹配 比较简单 功能不全 class UserInfoSerializer2(serializers.Serializer): # 枚举choices的处理 class meta: model = UserInfo fields = "__all__" # 显示全部 # fields = ["id","username","password","oooo"] class UserinfoView(APIView): def get(self, request, *args, **kwargs): res = API_TEMPLATE.copy() users = UserInfo.objects.all() ser = UserInfoSerializer(instance=users, many=True) print("OrderedDict", ser.data) ret = json.dumps(ser.data, ensure_ascii=False) res.update(code=HttpCode.ok.value[0], msg=HttpCode.ok.value[1], data=ret) return JsonResponse(res)
8.2 请求数据的验证
-
POST数据验证
class TitleValidator(object): """自定义验证规则""" def __init__(self, base): self.base = str(base) def __call__(self, value): if not value.startswith(self.base): message = "this field must start with %s" % self.base raise serializers.ValidationError(message) def set_context(self,serializer_field): pass class UsergroupSerializer(serializers.Serializer): title = serializers.CharField(error_messages={"required": "标题不能为空"}, validators=[TitleValidator("老男孩")]) class UsergroupView(APIView): def post(self, request, *args, **kwargs): print(request.data) # data 要验证的数据 # validators 自定义验证规则 ser = UsergroupSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data) return HttpResponse(ser.validated_data) else: print(ser.errors) return HttpResponse(ser.errors) -
勾子函数如何写?
9. DRF生产URL
9.1 基本使用
-
再url中命名
re_path(r'^/group/(?P<pk>\d+)$', GroupView.as_view(), name="gp") -
再序列化类中加
serializers.HyperlinkedIdentityFieldclass UserInfoSerializer(serializers.Serializer): group = serializers.HyperlinkedIdentityField(view_name="gp", lookup_field="group_id", lookup_url_kwarg="pk") class meta: model = UserInfo fields = "__all__" # 显示全部 -
序列化中要加一个配置
context={"request":request}ser = UserInfoSerializer(instance=users, many=True,context={"request":request}) -
代码
class UserInfoSerializer(serializers.Serializer): # 枚举choices的处理 group = serializers.HyperlinkedIdentityField(view_name="gp", lookup_field="group_id", lookup_url_kwarg="pk") class meta: model = UserInfo fields = "__all__" # 显示全部 # fields = ["id","username","password","group","roles"] class UserinfoView(APIView): def get(self, request, *args, **kwargs): res = API_TEMPLATE.copy() users = UserInfo.objects.all() ser = UserInfoSerializer(instance=users, many=True,context={"request":request}) ret = json.dumps(ser.data, ensure_ascii=False) res.update(code=HttpCode.ok.value[0], msg=HttpCode.ok.value[1], data=ret) return JsonResponse(res)
10.DRF分页
- 分页,看第几页 ,每页显示多少数据
- 分页,在某个位置,向后查询多少条数据
- 加密分页,只能看上一页和下一页
10.1 基本使用
- 基本分页 看第几页 ,每页显示多少数据
from api.order.utils.serializers.pages import PagerSerializer
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
class MyPagination(PageNumberPagination):
# url中转换分页的参数
page_query_param = "page"
# 每页显示几个
page_size = 2
# 定制显示几个
page_size_query_param = "size"
# 最多显示几个
max_page_size = 5
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
# 获取所有数据
roles = Role.objects.all()
# 创建分页对象
pg = MyPagination()
# 对数据分页
pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)
# 序列化
ser = PagerSerializer(instance=pager_roles, many=True)
# return Response(ser.data)
return pg.get_paginated_response(ser.data)
class PagerSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField()
- 分页,在某个位置,向后查询多少条数据
from api.order.utils.serializers.pages import PagerSerializer
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
class MyLimitPagination(LimitOffsetPagination):
"""在某个位置 向后查询多少条数据"""
# 从第几条开始
offset_query_param = 'offset'
# 显示几个
limit_query_param = 'limit'
# 默认显示2个
default_limit = 2
# 最多显示10个
max_limit = 10
class Pager1View(APIView):
def get(self, request, *args, **kwargs):
# 获取所有数据
roles = Role.objects.all()
# 创建分页对象
# pg = MyPagination()
pg = MyLimitPagination()
pg = MyCursorPagination()
# 对数据分页
pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)
# 序列化
ser = PagerSerializer(instance=pager_roles, many=True)
# return Response(ser.data)
return pg.get_paginated_response(ser.data)
10.2 数据量大如何分页
- 数据库相关
- 索引
- 分页
11.DRF视图
11.1基本使用
- GenericAPIView(无用)
from rest_framework.generics import GenericAPIView
class v1View(GenericAPIView):
"""
url:/api/v1/user/v1view
"""
queryset = Role.objects.all()
serializer_class = PagerSerializer
pagination_class = PageNumberPagination
def get(self, request, *args, **kwargs):
# 获取数据
roles = self.get_queryset()
# 分页
pager_roles = self.paginate_queryset(roles)
# 序列化
self.get_serializer(instance=pager_roles, many=True)
return Response("111")
- GenericViewSet(可以修改方法名称)
from rest_framework.viewsets import GenericViewSet
class v1View(GenericViewSet):
"""
可以修改get和post的方法名称
"""
queryset = Role.objects.all()
serializer_class = PagerSerializer
pagination_class = PageNumberPagination
def list(self, request, *args, **kwargs):
# 获取数据
roles = self.get_queryset()
# 分页
pager_roles = self.paginate_queryset(roles)
# 序列化
self.get_serializer(instance=pager_roles, many=True)
return Response("111")
- ModelViewSet(功能最强大)
from rest_framework.viewsets import ModelViewSet
# ModelViewSet继承了ListModelMixin, UpdateModelMixin, CreateModelMixin, DestroyModelMixin等6个试
# 分别代表增删改查和局部更新
11.2 总结
- 用增删改查
- ModelViewSet
- 用增删
- CreateModelMixin,DestroyModelMixin,GenericViewSet
- 复杂逻辑
- APIView
12.DRF路由
url(r'^(?P<version>[v1|v2]+)/users/$'.views.UserView.as_view(),name="User")
url(r'^(?P<version>[v1|v2]+)/view1/$'.views.UserView.as_view({"get":"list","delete":"destory","put":"update","post":"created"}),name="User")
13.DRF解析器
# 页面形式
127.0.0.1:8000/api/v1/user
# json形式
127.0.0.1:8000/api/v1/user?format=json
14.DRF渲染器
from rest_framework.renderers import AdminRenderer,JSONRenderer,BrowsableAPIRenderer,HTMLFormRenderer
class TestView(APIView):
"""
AdminRenderer Admin渲染器
JSONRenderer json渲染器
BrowsableAPIRenderer 浏览器渲染器
HTMLFormRenderer 表单渲染器
"""
renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
"DEFAULT_RENDERER_CLASSES":[
"rest_framework.renderers.AdminRenderer",
"rest_framework.renderers.JSONRenderer",
"rest_framework.renderers.BrowsableAPIRenderer"
]

浙公网安备 33010602011771号