特点:
提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
丰富的定制层级:函数视图、类视图、视图集合到自动生成 API。 django 针对 Web 开发中常见的处理逻辑,提供了各种通用视图函数,以提高代码的复用性,减少开发者的工作量。django-rest-framework 同样针对 RESTful API 开发中常见的处理逻辑,提供了各种通用视图函数
多种身份认证和权限认证方式的支持内置了限流系统;自动生成API文档。前后端分离开发
除此以外,django-rest-framework 还提供了分页(Pagination)、API 版本控制(Versioning)、缓存(Caching)、限流(Throtting)等各种功能类
安装:
CodeBlock Loading...
Python (3.7.3)
Django(3.0.1)
我们首先来回顾一下传统的基于模板引擎的 django 开发工作流:
其实,基于 django-rest-framework 的 RESTful API 的开发,过程是完全类似的:
rest_framework.serializers.Serializer
作用
进行数据的校验
对数据对象进行转换 ORM->JSON
可以操作数据增删改查
DRF中的Serializer
使用类来定义,须继承自rest_framework.serializers.Serializer
参数名称 | 说明 |
---|---|
read_only | 表明该字段仅用于序列化输出,默认False |
write_only | 表明该字段仅用于反序列化输入,默认False |
required | 表明该字段在反序列化时必须输入,默认True |
default | 反序列化时使用的默认值 |
allow_null | 表明该字段是否允许传入None,默认False |
validators | 该字段使用的验证器 |
error_messages | 包含错误编号与错误信息的字典 |
label | 用于HTML展示API页面时,显示的字段名称 |
help_text | 用于HTML展示API页面时,显示的字段帮助提示信息 |
使用
最基本的使用
获取单个序列化数据
获取多个序列化数据
关联对象嵌套序列化
在使用序列化器进行反序列化时,需要对数据进行验证后,才获取成功数据保存模型对象
在获取反序列化数据前,必须调用is_valid() 方法进行验证。 成功True 失败False
验证成功通过序列化器对象的validated_data 属性获取数据
同时序列化器提供了其他验证方式
验证单个字段
验证多个字段
保存数据
验证成功后,就可以将数据保存成模型存入数据库。
可以通过实现create()
和update()
两个方法来实现
如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类
ModelSerializer与常规的Serializer相同,但提供了:
- 基于模型类自动生成一系列字段
- 基于模型类自动为Serializer生成validators,比如unique_together
- 包含默认的create()和update()的实现
可以通过shell
命令查看具体实现
1) 使用 fields
来明确字段,__all__
表名包含所有字段,也可以写明具体哪些字段
2) 使用 exclude
可以明确排除掉哪些字段
3) 显示指明字段
4) 指明只读字段
可以通过readonlyfields指明只读字段,即仅用于序列化输出的字段
可以使用 extra_kwargs
参数为ModelSerializer
添加或修改原有的选项参数
REST framework
传入DRF封装后视图的request
对象不再是Django
默认的HttpRequest
对象,而是REST framework
提供的扩展了HttpRequest
类的Request
类的对象
REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中
Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。
无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。
无论前端发过来的是xml还是json,请求方式无论是POST还是PUT,都可以直接用request.data直接取一个字典出来
要继承APIView(或其子类)才能取得DRF的Request和Response
request.queryparams 查询参数。 为了代码更加清晰准确,推荐使用`request.queryparams,而不是Django中的
request.GET`,这样那够让你的代码更加明显的体现出-----任何HTTP方法类型都可能包含查询参数(query parameters),而不仅仅只是'GET'请求。
request.data
返回解析之后的请求体(表单、json)数据。类似于Django中标准的request.POST
和 request.FILES
属性,但提供如下特性:
rest_framework.response.Response
REST framework提供了一个响应类Response
,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型
参数说明:
data
: 为响应准备的序列化处理后的数据;status
: 状态码,默认200;template_name
: 模板名称,如果使用HTMLRenderer
时需指明;headers
: 用于存放响应头信息的字典;content_type
: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
REST framewrok
在rest_framework.status
模块中提供了常用状态码常量。
总是在你的视图中用数字的HTTP状态码会更加容易理解,并且如果你用其他错误代码表示错误,就不太容易注意到了。REST框架为每个状态码(status code)提供更明确的标识符,例如在状态(status)模型中的HTTP400BAD_REQUEST。用这些标识符代替纯数字的HTTP状态码是很好的注意
如果返回所有图书列表,不用再像以前JsonResponse
中需指定safe=False
了
APIView
是REST framework提供的所有视图的基类,继承自Django的View
父类
APIView
与View
的不同之处在于:
- 传入到视图方法中的是REST framework的
Request
对象,而不是Django的HttpRequeset
对象;- 视图方法可以返回REST framework的
Response
对象,视图会为响应数据设置(render)符合前端要求的格式;- 任何
APIException
异常都会被捕获到,并且处理成合适的响应信息;- 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制
支持定义的属性:
- authentication_classes 列表或元祖,身份认证类
- permissoin_classes 列表或元祖,权限检查类
- throttle_classes 列表或元祖,流量控制类
在APIView
中仍以常规的类视图定义方法来实现get() 、post() 或者其他请求方式的方法
rest_framework.generics.GenericAPIView
继承自APIVIew
,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类
pk
'列表视图与详情视图通用:
get_queryset(self)
返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset
属性,可以重写,例如:
getserializerclass(self)
返回序列化器类,默认返回serializer_class
,可以重写,例如:
返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。
注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
详情视图使用:
get_object(self) 返回详情视图所需的模型类数据对象,默认使用lookup_field
参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。
若详情访问的模型类对象不存在,会返回404。
该方法会默认使用APIView
提供的checkobjectpermissions方法检查当前对象是否有权限被访问。
mixins 翻译 是 组件、混入的意思。
在DRF中针对获取列表、检索、创建等操作。都有响应的mixins
ListModelMixin
列表视图扩展类,提供list(request, *args, **kwargs)
方法快速实现列表视图,返回200状态码。
CreateModelMixin
创建视图扩展类,提供create(request, *args, **kwargs)
方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。
RetrieveModelMixin
详情视图扩展类,提供retrieve(request, *args, **kwargs)
方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。
UpdateModelMixin
更新视图扩展类,提供update(request, *args, **kwargs)
方法,可以快速实现更新一个存在的数据对象。同时也提供partial_update(request, *args, **kwargs)
方法,可以实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。
DestroyModelMixin
删除视图扩展类,提供destroy(request, *args, **kwargs)
方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
同故宫mixin可以非常方便实现一些CRUD操作。
CreateAPIView
实现创建数据的
提供 post 方法
继承自: GenericAPIView、CreateModelMixin
ListAPIView
实现获取列表的
提供 get 方法
继承自:GenericAPIView、ListModelMixin
RetireveAPIView
实现检索数据的
提供 get 方法
继承自: GenericAPIView、RetrieveModelMixin
DestoryAPIView
实现删除数据的
提供 delete 方法
继承自:GenericAPIView、DestoryModelMixin
UpdateAPIView
实现更新数据的
提供 put 和 patch 方法
继承自:GenericAPIView、UpdateModelMixin
RetrieveUpdateAPIView
提供 get、put、patch方法
继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
使用视图集
ViewSet
,可以将一系列逻辑相关的动作放到一个类中:
- list() 提供一组数据
- retrieve() 提供单个数据
- create() 创建数据
- update() 保存数据
- destory() 删除数据
ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。
视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。
在设置路由时,我们可以如下操作
在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个
继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法
继承自GenericAPIView
,作用也与GenericAPIVIew类似,提供了getobject、getqueryset等方法便于列表视图与详情信息视图的开发
继承自GenericAPIVIew
,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。所以所有增删改查功能都具备
继承自GenericAPIVIew
,同时包括了ListModelMixin、RetrieveModelMixin
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。
添加自定义动作需要使用rest_framework.decorators.action
装饰器。
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。
REST framework提供了两个router
SimpleRouter
DefaultRouter
使用方法
导入rest_framework.decorators.action
装饰器可解决上面问题。
要使用自动生成路由的方法,视图必须继承自视图集。
除了SimpleRouter
,还有DefaultRouter
,区别在于后者能生成首页,而前者不能。
使用视图集只能处理前端通过request发过来的数据是表单或json数据的类型。
DRF 内置认证模块
配置分为全局配置|局部配置在每个视图中通过设置authentication_classess属性来设置
基本的授权。 每次都要在Header中把用户名和密码传给服务器。
基于Django的session机制实现的
缺点没有自动过期机制。一旦登录token永久。
JWT是在成功后,把用户的相关信息以及过期时间进行加密。然后生成一个token来返回给客户端。 客户端拿到可以存储起来。以后每次请求的时候都携带这个token。 服务器在接收到需要登录的API的请求。 对这个token进行解密。 然后获取用户过期时间和用户信息。 如果过期了或者用户的信息不对。都是认证失败
全局配置
局部配置
认证失败会有两种可能的返回值:
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问
全局配置
默认配置
局部配置
也可以在具体的视图中通过permission_classes属性来设置
提供的权限
- AllowAny 允许所有用户
- IsAuthenticated 仅通过认证的用户
- IsAdminUser 仅管理员用户
- IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取
可以对接口访问的频次进行限制,以减轻服务器压力。
一般用于付费购买次数,投票等场景使用.
可以对接口访问的频次进行限制,以减轻服务器压力,主要用于反爬虫
全局配置
DEFAULT_THROTTLE_RATES
可以使用second
,minute
,hour
或day
来指明周期。限制视图接口被访问的频率次数 - 限制的条件(IP、id、唯一键)、频率周期时间(s、m、h)、频率的次数(3/s)
局部配置
可选限流类
DRF中,节流的类总共三个
1)
AnonRateThrottle
限制所有匿名未认证用户,使用IP区分用户。
使用
DEFAULT_THROTTLE_RATES['anon']
来设置频次2)
UserRateThrottle
限制认证用户,使用User id 来区分。
使用
DEFAULT_THROTTLE_RATES['user']
来设置频次如果想要针对不同类型的用户实现不同策略的节流,我们可以通过继承UserRateThrottle类,然后设置scope属性
然后再
settings.py
中配置CodeBlock Loading...3)
ScopedRateThrottle
限制用户对于每个视图的访问频次,使用ip或user id。
这个不管是登录还是未登录。都是根据scope来实现的。
CodeBlock Loading...
对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持,实现了ListModelMixin
扩展类及子类的视图类才能使用
在配置文件中增加过滤后端的设置
在视图中添加filter_fields属性,指定可以过滤的字段
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序
使用方法:
在类视图中设置filterbackends,使用restframework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。
如果需要在过滤以后再次进行排序,则需要两者结合!
REST framework提供了分页的支持。
我们可以在配置文件中设置全局的分页方式,如
也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_class属性来指明
1. PageNumberPagination
注意:如果在视图内关闭分页功能,只需在视图内设置
2. LimitOffsetPagination
http://127.0.0.1:8888/book/?limit=20&offset=10
可以在子类中定义的属性
defaultlimit 默认限制,默认值与`PAGESIZE`设置一直
limitqueryparam limit参数名,默认'limit'
offsetqueryparam offset参数名,默认'offset'
max_limit 最大limit限制,默认None
REST framework提供了异常处理,我们可以自定义异常处理函数。
全局配置
如果未声明,会采用默认的方式,如下
REST framework定义的异常
APIException 所有异常的父类
ParseError 解析错误
AuthenticationFailed 认证失败
NotAuthenticated 尚未认证
PermissionDenied 权限决绝
NotFound 未找到
MethodNotAllowed 请求方式不支持
NotAcceptable 要获取的数据格式不支持
Throttled 超过限流次数
ValidationError 校验失败
pip install djangorestframework
class BookSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField( read_only=True)
title = serializers.CharField( max_length=20)
read_only
指定只参与序列化,max_length
限定字符串最大长度。字段里不传参数序列化与反序列化都参与
serializer
不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer
是独立于数据库之外的存在
readonly表示只能读,不能进行修改。例如定义序列化器时,id字段通常指定readonly=True。在序列化时,即对象转为字典、JSON字符串时,字典、JSON字符串包含着id字段。但是反序列化时,即JSON字符串、字典转换为对象时,在参数校验的时候,即使字典有id的键值对,校验不会出错,但是校验后的数据不会有id这个字段,所以id也不会存进数据库。
writeonly表示只能写,不能读。例如定义序列化器时,password字段(还有短信验证码等)通常指定writeonly=True。在序列化时,即对象转为字典、JSON字符串时,字典、JSON字符串不会包含着字段。但是反序列化时,即JSON字符串、字典转换为对象时,在参数校验的时候,校验通过,而且校验后的数据有password这个字段,并且能存进数据库。
Serializer的构造函数的参数
serializer.data
serializer = BookSerializer(books, many=True)
serializer.data
heroes = HeroInfoSerializer(many=True) # 根据指定的HeroSerialzier序列化中指定的字段返回
class BookView(View):
# 更新操作
def put(self, request, pk):
data = json.loads(request.body.decode())
try:
# 从模型取数据
book = BookInfo.objects.get(pk=pk)
except Exception:
return JsonResponse({'errors': '未找到该书'})
ser = BookInfoSerializer(book, data=data)
ser.is_valid(raise_exception=True)
class BookSerializer(serializers.Serializer):
def validated_title(self, value):
if value == 'python':
raise serializers.ValidationError('书名python错误')
return value
class BookSerializer(serializers.Serializer):
...
def validate(self, attrs):
bread = attrs['bread']
bcomment = attrs['bcomment']
if bread < bcomment:
raise serializers.ValidationError('阅读量小于评论量')
return attrs
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = '__all__' # 返回所有字段
model 指明参照哪个模型类
fields 指明为模型类的哪些字段生成
>>> from booktest.serializers import BookSerializer # 导入
>>> serializer = BookSerializer() # 序列化
>>> serializer
BookSerializer():
id = IntegerField(label='ID', read_only=True)
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo # 指定根据哪个模型类来序列化
fields = ('id', 'btitle', 'bpub_date')
class HeroInfoSerializer(serializers.ModelSerializer):
hbook = BookInfoSerializer()
class Meta:
model = HeroInfo
fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook')
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
extra_kwargs = {
'bread': {'min_value': 0, 'required': True},
'bcomment': {'min_value': 0, 'required': True},
}
from .models import *
from .serializer import *
from rest_framework.decorators import api_view
from rest_framework.response import Response # Response
from rest_framework import status # status
@api_view(http_method_names=['get','post'])
def index(request):
'''
展示所有图书
:param request:
:return:
'''
if request.method == 'GET':
serializer = BookSerializer(Book.objects.all(), many=True)
return Response(serializer.data)
if request.method == 'POST':
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
# 自定义状态码
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
rest_framework.views.APIView
from rest_framework.views import APIView
from rest_framework.response import Response
# url(r'^books/$', views.BookListView.as_view()),
class BookListView(APIView):
def get(self, request):
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True)
return Response(serializer.data)
def get_queryset(self):
user = self.request.user
return user.accounts.all()
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
from rest_framework.generics import GenericAPIView
class BooksView(GenericAPIView):
queryset = BookInfo.objects.all() #指定查询集
serializer_class = BookInfoSerializer # 指定序列化器
def get(self, request):
'''查询所有图书'''
books = self.get_queryset() 获取查询集
# book = self.get_object() 获取单一数据对象
serializer = self.get_serializer(books, many = True) #获取序列化器
return Response(serializer.data)
def post(self, request):
"""
保存图书
"""
# 1、获取前端数据
data = request.data
# 2、验证数据
ser = self.get_serializer(data=data)
ser.is_valid(raise_exception=True)
# 3、保存数据
ser.save()
# 4、返回结果
return Response(ser.data)
from rest_framework import mixins
from rest_framework import generics
class BookView(
generics.GenericAPIView,
mixins.ListModelMixin, # 列表视图扩展类
mixins.RetrieveModelMixin, # 详情视图扩展类
mixins.CreateModelMixin, # 创建视图扩展类
mixins.UpdateModelMixin, # 更新视图扩展类
mixins.DestroyModelMixin # 删除视图扩展类
):
'''
图书控制层
列表 /book
新增 /book/
详情 /book/pk/
修改 /book/pk
删除 /book/pk
'''
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, pk=None):
if pk:
return self.retrieve(request)
else:
return self.list(request)
def post(self, request):
return self.create(request)
def put(self, request, pk=None):
return self.update(request)
def delete(self, request):
return self.delete(request)
from rest_framework.mixins import ListModelMixin
class BooksView(ListModelMixin, GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
def get(self, request):
return self.list(request)
from rest_framework.mixins import CreateModelMixin
class BooksView(CreateModelMixin, GenericAPIView):
serializer_class = BookInfoSerializer
def post(self, request):
return self.create(request)
class BooksView(RetrieveModelMixin, GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
def get(self, request, pk):
return self.retrieve(request)
from rest_framework import generics
class BookView(
generics.CreateAPIView,
generics.UpdateAPIView,
generics.DestroyAPIView,
generics.RetrieveAPIView
):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookInfoViewSet(viewsets.ViewSet):
# 展示所有
def list(self, request):
...
# 展示单个
def retrieve(self, request, pk=None):
...
urlpatterns = [
url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]
def get_serializer_class(self):
if self.action == 'create':
return OrderCommitSerializer
else:
return OrderDataSerializera
# 路由层
url(r'^books/$', view_set.BooksModelViewSet.as_view({'get': 'list', 'post': 'create'})),
url(r'^books/(?P<pk>\d+)/$', view_set.BooksModelViewSet.as_view({'get': 'retrieve','put':'update','delete':'destroy'})),
from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
只读API
"""
queryset = User.objects.all()
serializer_class = UserSerializer
from rest_framework import routers
from django.conf.urls import include,url
# 创造和定义路由地址
route = routers.DefaultRouter()
# 注册路由地址
route.register("book", views.BookView)
route.register('tag',views.TagView)
urlpatterns = [
]+route.urls
1) 创建router对象,并注册视图集
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'books', BookInfoViewSet, base_name='book')
##############################
register(prefix, viewset, base_name)
- prefix 该视图集的路由前缀
- viewset 视图集
- base_name 路由名称的前缀
# 上述代码会形成的路由如下
^books/$ name: book-list
^books/{pk}/$ name: book-detail
2)添加路由数据
urlpatterns = [ ...]
urlpatterns += router.urls
# 或者
urlpatterns = [ ..., url(r'^', include(router.urls))]
...
from rest_framework.decorators import action
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
@action(methods=['get'], detail=False) #detail = False不生成正则匹配
def latest(self, request, pk):
...
@action(methods=['put'], detail=True)#detail = True生成正则匹配
def read(self, request, pk):
...
from rest_framework.authentication import BaseAuthentication
from rest_framework.authentication import SessionAuthentication
from rest_framework.authentication import TokenAuthentication
from rest_framework.authentication import RemoteUserAuthentication
from rest_framework.authentication import BasicAuthentication
from .models import *
from .serializer import *
from rest_framework.views import APIView
from rest_framework import viewsets
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated
class BookView(viewsets .ModelViewSet):
'''
图书控制层
'''
queryset = Book.objects.all()
serializer_class = BookSerializer
# 类属性
# 验证用户是否已经成功登录
authentication_classes = [BasicAuthentication]
# 验证用户的权限来限制访问
permission_classes = [IsAuthenticated]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 基本表单认证
'rest_framework.authentication.SessionAuthentication', # session认证
)
}
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = (SessionAuthentication, BasicAuthentication)
...
from rest_framework.permissions import IsAuthenticated
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', # 授权访问
)
}
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import ModelViewSet
BooksModelViewSet(ModelViewSet):
permission_classes = (IsAuthenticated,) #登录授权用户
...
from rest_framework.authentication import SessionAuthentication # Session 认证
from rest_framework.permissions import IsAuthenticated # 权限
from rest_framework.generics import RetrieveAPIView
class BookListView(RetrieveAPIView):
queryset = BookInfo.objects.all() # 查询
serializer_class = BookInfoSerializer # 序列化
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '4/day', # 匿名用户每天访问4次
'user': '100/day' # 登录用户访问100次
}
}
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView # 视图
class BookListView(APIView):
throttle_classes = (UserRateThrottle,)
...
class AdminRateThrottle(UserRateThrottle):
scope = 'admin'
'DEFAULT_THROTTLE_RATES':{
'normal': '60/day',
'admin': '1000/day'
}
class ConListView(APIView):
throttle_scope = 'uploads'
...
from rest_framework.authentication import SessionAuthentication # Session认证
from rest_framework.permissions import IsAuthenticated # 权限
from rest_framework.generics import RetrieveAPIView # 视图
from rest_framework.throttling import UserRateThrottle # 限速
class BooksView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]
throttle_classes = (UserRateThrottle,)
...
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
pip install django-filter
> 2.2.0
INSTALLED_APPS = [
...
'django_filters', # 需要注册应用,
]
REST_FRAMEWORK = {
...
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
from django_filters.rest_framework import DjangoFilterBackend
class BookView(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend]
filter_fields = ('id',)
http://127.0.0.1:8888/book/?id=3
from rest_framework.filters import OrderingFilter
class StudentListView(ListAPIView):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
filter_backends = [OrderingFilter]
#ordering_fields = ('id', 'age')
ordering_fields = '__all__'
# 127.0.0.1:8000/books/?ordering=-id
# -id 表示针对id字段进行倒序排序
# id 表示针对id字段进行升序排序
# 如果有ordering_fields
# url输入的是该字段,就按该字段排序(ordering_fields必须是可以参与order_by()的字段,否则会报错)否则不排序
# 如果ordering_fields = '__all__':
# 1. 如 url:/ordering = -sdfsfd,则 ordering = None,不排序
# 2. 如 url:/ordering = -price, 则 ordering = -price,按-price排序
# 如果没有指定ordering_fields,
# 1. 不参与序列化,如:sdsadf。则 ordering = None,不排序
# 2. 参与序列化且是表字段,如:price,则 ordering = price, 按price排序,
# 3. 参与序列化不是表字段,如:brand_name, 则 ordering = brand_name,报错(order_by(brand_name)出错
from rest_framework.generics import ListAPIView
from students.models import Student
from .serializers import StudentModelSerializer
from django_filters.rest_framework import DjangoFilterBackend
class Student3ListView(ListAPIView):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
filter_fields = ('age', 'sex')
# 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,
# 否则过滤功能会失效
filter_backends = [OrderingFilter,DjangoFilterBackend]
ordering_fields = ('id', 'age')
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每页数目
}
from rest_framework.pagination import PageNumberPagination #分页
class LargeResultsSetPagination(PageNumberPagination):
"""
配置分页规则
"""
page_size = 5 # 每页数目
page_size_query_param = 'page_size' # 前端发送的页数关键字名,默认为"page"
page_query_param = 'page' # 前端发送的每页数目关键字名,默认为None
max_page_size = 10000 # 前端最多能设置的每页数量
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
pagination_class = LargeResultsSetPagination # 应用到视图函数中
pagination_class = None
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
}
from rest_framework.pagination import LimitOffsetPagination
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = LimitOffsetPagination
# 127.0.0.1:8000/books/?offset=3&limit=2
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
# 先调用REST framework默认的异常处理方法获得标准错误响应对象
response = exception_handler(exc, context)
# 在此处补充自定义的异常处理
if response is not None:
response.data['status_code'] = response.status_code
return response
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'#定义处理异常的路径,以项目实际为准
}
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}