Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具。前端
一般简称为DRF框架 或 REST framework。python
特色
提供了定义序列化器Serializer的方法,能够快速根据 Django ORM 或者其它库自动序列化/反序列化;
提供了丰富的类视图、Mixin扩展类,简化视图的编写;
丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,知足各类须要;
多种身份认证和权限认证方式的支持;
内置了限流系统;
直观的 API web 界面;
可扩展性,插件丰富
环境安装与配置
1. 安装DRF
pip install djangorestframework
2. 添加rest_framework应用
咱们利用在Django框架学习中建立的demo工程,在settings.py的INSTALLED_APPS中添加'rest_framework'。web
INSTALLED_APPS = [
...
'rest_framework',
]
见识DRF的魅力
1. 建立序列化器
在booktest应用中新建serializers.py用于保存该应用的序列化器。数据库
建立一个BookInfoSerializer用于序列化与反序列化。django
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = '__all__'
model 指明该序列化器处理的数据字段从模型类BookInfo参考生成
fields 指明该序列化器包含模型类中的哪些字段,'__all__'指明包含全部字段
2. 编写视图
在booktest应用的views.py中建立视图BookInfoViewSet,这是一个视图集合。json
from rest_framework.viewsets import ModelViewSet
from .serializers import BookInfoSerializer
from .models import BookInfo
class BookInfoViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
queryset 指明该视图集在查询数据时使用的查询集
serializer_class 指明该视图在进行序列化或反序列化时使用的序列化器
3. 定义路由
在booktest应用的urls.py中定义路由信息。后端
from . import views
from rest_framework.routers import DefaultRouter
urlpatterns = [
...
]
router = DefaultRouter() # 能够处理视图的路由器
router.register(r'books', views.BookInfoViewSet) # 向路由器中注册视图集
urlpatterns += router.urls # 将路由器中的因此路由信息追到到django的路由列表中
api
Serializer序列化器
1. 建立Serializer对象
定义好Serializer类后,就能够建立Serializer对象了。浏览器
Serializer的构造方法为:服务器
Serializer(instance=None, data=empty, **kwarg)
说明:
1)用于序列化时,将模型类对象传入instance参数
2)用于反序列化时,将要被反序列化的数据传入data参数
3)除了instance和data参数外,在构造Serializer对象时,还可经过context参数额外添加数据,如
serializer = AccountSerializer(account, context={'request': request})
经过context参数附加的数据,能够经过Serializer对象的context属性获取。
2. 基本使用
1) 先查询出一个图书对象
from booktest.models import BookInfo
book = BookInfo.objects.get(id=2)
2) 构造序列化器对象
from booktest.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book)
3)获取序列化数据
经过data属性能够获取序列化后的数据
serializer.data
# {'id': 2, 'btitle': '天龙八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}
4)若是要被序列化的是包含多条数据的查询集QuerySet,能够经过添加many=True参数补充说明
book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data
# [OrderedDict([('id', 2), ('btitle', '天龙八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bco
3. 关联对象嵌套序列化
若是须要序列化的数据中包含有其余关联对象,则对关联对象数据的序列化须要指明。
1) PrimaryKeyRelatedField
此字段将被序列化为关联对象的主键。
hbook = serializers.PrimaryKeyRelatedField(label='图书', read_only=True)
或
hbook = serializers.PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())
指明字段时须要包含read_only=True或者queryset参数:
包含read_only=True参数时,该字段将不能用做反序列化使用
包含queryset参数时,将被用做反序列化时参数校验使用
2) StringRelatedField
此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)
hbook = serializers.StringRelatedField(label='图书')
3)HyperlinkedRelatedField
此字段将被序列化为获取关联对象数据的接口连接
hbook = serializers.HyperlinkedRelatedField(label='图书', read_only=True, view_name='books-detail')
必须指明view_name参数,以便DRF根据视图名称寻找路由,进而拼接成完整URL。
4)SlugRelatedField
此字段将被序列化为关联对象的指定字段数据
hbook = serializers.SlugRelatedField(label='图书', read_only=True, slug_field='bpub_date')
slug_field指明使用关联对象的哪一个字段
5)使用关联对象的序列化器
自定义序列化器对象
hbook = BookInfoSerializer()
6) 重写to_representation方法
序列化器的每一个字段实际都是由该字段类型的to_representation方法决定格式的,能够经过重写该方法来决定格式。
注意,to_representations方法不只局限在控制关联对象格式上,适用于各个序列化器字段类型。
自定义一个新的关联字段:
class BookRelateField(serializers.RelatedField):
"""自定义用于处理图书的字段"""
def to_representation(self, value):
return 'Book: %d %s' % (value.id, value.btitle)
指明hbook为BookRelateField类型
hbook = BookRelateField(read_only=True)
many参数
若是关联的对象数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每一个BookInfo对象关联的英雄HeroInfo对象可能有多个,此时关联字段类型的指明仍可以使用上述几种方式,只是在声明关联字段时,多补充一个many=True参数便可。
此处仅拿PrimaryKeyRelatedField类型来举例,其余相同。
反序列化使用
1. 验证
使用序列化器进行反序列化时,须要对数据进行验证后,才能获取验证成功的数据或保存成模型类对象。
在获取反序列化的数据前,必须调用is_valid()方法进行验证,验证成功返回True,不然返回False。
验证失败,能够经过序列化器对象的errors属性获取错误信息,返回字典,包含了字段和字段的错误。若是是非字段错误,能够经过修改REST framework配置中的NON_FIELD_ERRORS_KEY来控制错误字典中的键名。
验证成功,能够经过序列化器对象的validated_data属性获取数据。
在定义序列化器时,指明每一个字段的序列化类型和选项参数,自己就是一种验证行为。
is_valid()方法还能够在验证失败时抛出异常serializers.ValidationError,能够经过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)
1)validate_<field_name>
对<field_name>字段进行验证,如
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
...
def validate_btitle(self, value):
if 'django' not in value.lower():
raise serializers.ValidationError("图书不是关于Django的")
return value
2)validate
在序列化器中须要同时对多个字段进行比较验证时,能够定义validate方法来验证,如
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
...
def validate(self, attrs):
bread = attrs['bread']
bcomment = attrs['bcomment']
if bread < bcomment:
raise serializers.ValidationError('阅读量小于评论量')
return attrs
3)validators
在字段中添加validators选项参数,也能够补充验证行为,如
def about_django(value):
if 'django' not in value.lower():
raise serializers.ValidationError("图书不是关于Django的")
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名称', max_length=20, validators=[about_django])
bpub_date = serializers.DateField(label='发布日期', required=False)
bread = serializers.IntegerField(label='阅读量', required=False)
bcomment = serializers.IntegerField(label='评论量', required=False)
image = serializers.ImageField(label='图片', required=False)
4)REST framework提供的validators:
UniqueValidator
单字段惟一,如
from rest_framework.validators import UniqueValidator
slug = SlugField(
max_length=100,
validators=[UniqueValidator(queryset=BlogPost.objects.all())]
)
UniqueTogetherValidation
联合惟一,如
from rest_framework.validators import UniqueTogetherValidator
class ExampleSerializer(serializers.Serializer):
# ...
class Meta:
validators = [
UniqueTogetherValidator(
queryset=ToDoItem.objects.all(),
fields=('list', 'position')
)
]
2. 保存
若是在验证成功后,想要基于validated_data完成数据对象的建立,能够经过实现create()和update()两个方法来实现。
from db.serializers import BookInfoSerializer
data = {'btitle': '封神演义'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 封神演义>
from db.models import BookInfo
book = BookInfo.objects.get(id=2)
data = {'btitle': '倚天剑'}
serializer = BookInfoSerializer(book, data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 倚天剑>
book.btitle # '倚天剑'
若是建立序列化器对象的时候,没有传递instance实例,则调用save()方法的时候,create()被调用,相反,若是传递了instance实例,则调用save()方法的时候,update()被调用。
1) 在对序列化器进行save()保存时,能够额外传递数据,这些数据能够在create()和update()中的validated_data参数获取到
serializer.save(owner=request.user)
2)默认序列化器必须传递全部required的字段,不然会抛出验证异常。可是咱们可使用partial参数来容许部分字段更新
# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)
模型类序列化器ModelSerializer
若是咱们想要使用序列化器对应的是Django的模型类,DRF为咱们提供了ModelSerializer模型类序列化器来帮助咱们快速建立一个Serializer类。
ModelSerializer与常规的Serializer相同,但提供了:
基于模型类自动生成一系列字段
基于模型类自动为Serializer生成validators,好比unique_together
包含默认的create()和update()的实现
1. 定义
好比咱们建立一个BookInfoSerializer
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = '__all__'
model 指明参照哪一个模型类
fields 指明为模型类的哪些字段生成
2. 指定字段
1) 使用fields来明确字段,__all__表名包含全部字段,也能够写明具体哪些字段,如
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date')
2) 使用exclude能够明确排除掉哪些字段
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
exclude = ('image',)
3) 默认ModelSerializer使用主键做为关联字段,可是咱们可使用depth来简单的生成嵌套表示,depth应该是整数,代表嵌套的层级数量。如:
class HeroInfoSerializer2(serializers.ModelSerializer):
class Meta:
model = HeroInfo
fields = '__all__'
depth = 1
造成的序列化器以下:
HeroInfoSerializer():
id = IntegerField(label='ID', read_only=True)
hname = CharField(label='名称', max_length=20)
hgender = ChoiceField(choices=((0, 'male'), (1, 'female')), label='性别', required=False, validators=[<django.core.valators.MinValueValidator object>, <django.core.validators.MaxValueValidator object>])
hcomment = CharField(allow_null=True, label='描述信息', max_length=200, required=False)
hbook = NestedSerializer(read_only=True):
id = IntegerField(label='ID', read_only=True)
btitle = CharField(label='名称', max_length=20)
bpub_date = DateField(allow_null=True, label='发布日期', required=False)
bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
image = ImageField(allow_null=True, label='图片', max_length=100, required=False)
4) 显示指明字段,如:
class HeroInfoSerializer(serializers.ModelSerializer):
hbook = BookInfoSerializer()
class Meta:
model = HeroInfo
fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook')
5) 指明只读字段
能够经过read_only_fields指明只读字段,即仅用于序列化输出的字段
class BookInfoSerializer(serializers.ModelSerializer):
"""图书数据序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
read_only_fields = ('id', 'bread', 'bcomment')
3. 添加额外参数
咱们可使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
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},
}
视图
1. Request
REST framework 传入视图的request对象再也不是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。
REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中。
Request对象的数据是自动根据前端发送数据的格式进行解析以后的结果。
不管前端发送的哪一种格式的数据,咱们均可以以统一的方式读取数据。
经常使用属性
1).data
request.data 返回解析以后的请求体数据。相似于Django中标准的request.POST和 request.FILES属性,但提供以下特性:
包含了解析以后的文件和非文件数据
包含了对POST、PUT、PATCH请求方式解析后的数据
利用了REST framework的parsers解析器,不只支持表单类型数据,也支持JSON数据
2).query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
2. Response
rest_framework.response.Response
REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。
REST framework提供了Renderer 渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。若是前端请求中未进行Accept声明,则会采用默认方式处理响应数据,咱们能够经过配置来修改默认响应格式。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}
构造方式
Response(data, status=None, template_name=None, headers=None, content_type=None)
data数据不要是render处理以后的数据,只需传递python的内建类型数据便可,REST framework会使用renderer渲染器处理data。
data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据咱们可使用Serializer序列化器序列化处理后(转为了Python字典类型)再传递给data参数。
参数说明:
data: 为响应准备的序列化处理后的数据;
status: 状态码,默认200;
template_name: 模板名称,若是使用HTMLRenderer 时需指明;
headers: 用于存放响应头信息的字典;
content_type: 响应数据的Content-Type,一般此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
经常使用属性:
1).data
传给response对象的序列化后,但还没有render处理的数据
2).status_code
状态码的数字
3).content
通过render处理后的响应数据
3. 状态码
为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了经常使用状态码常量。
1)信息告知 - 1xx
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2)成功 - 2xx
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3)重定向 - 3xx
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4)客户端错误 - 4xx
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5)服务器错误 - 5xx
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
视图说明
1. 两个基类
1)APIView
rest_framework.views.APIView
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() 或者其余请求方式的方法。
举例:
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)
2)GenericAPIView
rest_framework.generics.GenericAPIView
继承自APIVIew,增长了对于列表视图和详情视图可能用到的通用支持方法。一般使用时,可搭配一个或多个Mixin扩展类。
支持定义的属性:
列表视图与详情视图通用:
queryset 列表视图的查询集
serializer_class 视图使用的序列化器
列表视图使用:
pagination_class 分页控制类
filter_backends 过滤控制后端
详情页视图使用:
lookup_field 查询单一数据库对象时使用的条件字段,默认为'pk'
lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同
提供的方法:
列表视图与详情视图通用:
get_queryset(self)
返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,能够重写,例如:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
get_serializer_class(self)
返回序列化器类,默认返回serializer_class,能够重写,例如:
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
get_serializer(self, args, *kwargs)
返回序列化器对象,被其余视图或扩展类使用,若是咱们在视图中想要获取序列化器对象,能够直接调用此方法。
注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象能够在定义序列化器时使用。
详情视图使用:
get_object(self) 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中能够调用该方法获取详情信息的模型类对象。
若详情访问的模型类对象不存在,会返回404。
该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。
举例:
# url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
class BookDetailView(GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
def get(self, request, pk):
book = self.get_object()
serializer = self.get_serializer(book)
return Response(serializer.data)
2. 五个扩展类
1)ListModelMixin
列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。
该Mixin的list方法会对数据进行过滤和分页。
2)CreateModelMixin
建立视图扩展类,提供create(request, *args, **kwargs)方法快速实现建立资源的视图,成功返回201状态码。
若是序列化器对前端发送的数据验证失败,返回400错误。
3) RetrieveModelMixin
详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,能够快速实现返回一个存在的数据对象。
若是存在,返回200, 不然返回404。
4)UpdateModelMixin
更新视图扩展类,提供update(request, *args, **kwargs)方法,能够快速实现更新一个存在的数据对象。
同时也提供partial_update(request, *args, **kwargs)方法,能够实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。
5)DestroyModelMixin
删除视图扩展类,提供destroy(request, *args, **kwargs)方法,能够快速实现删除一个存在的数据对象。
成功返回204,不存在返回404。
3. 几个可用子类视图
1) CreateAPIView
提供 post 方法
继承自: GenericAPIView、CreateModelMixin
2)ListAPIView
提供 get 方法
继承自:GenericAPIView、ListModelMixin
3)RetireveAPIView
提供 get 方法
继承自: GenericAPIView、RetrieveModelMixin
4)DestoryAPIView
提供 delete 方法
继承自:GenericAPIView、DestoryModelMixin
5)UpdateAPIView
提供 put 和 patch 方法
继承自:GenericAPIView、UpdateModelMixin
6)RetrieveUpdateAPIView
提供 get、put、patch方法
继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
视图集ViewSet
使用视图集ViewSet,能够将一系列逻辑相关的动做放到一个类中:
list() 提供一组数据
retrieve() 提供单个数据
create() 建立数据
update() 保存数据
destory() 删除数据
ViewSet视图集类再也不实现get()、post()等方法,而是实现动做 action 如 list() 、create() 等。
视图集只在使用as_view()方法的时候,才会将action动做与具体请求方式对应上。如:
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'})
]
action属性
在视图集中,咱们能够经过action对象属性来获取当前请求视图集时的action动做是哪一个。
例如:
def get_serializer_class(self):
if self.action == 'create':
return OrderCommitSerializer
else:
return OrderDataSerializer
经常使用视图集父类
1) ViewSet
继承自APIView,做用也与APIView基本相似,提供了身份认证、权限校验、流量管理等。
在ViewSet中,没有提供任何动做action方法,须要咱们本身实现action方法。
2)GenericViewSet
继承自GenericAPIView,做用也与GenericAPIVIew相似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。
3)ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。
视图集中定义附加action动做
在视图集中,除了上述默认的方法动做外,还能够添加自定义动做。
添加自定义动做须要使用rest_framework.decorators.action装饰器。
以action装饰器装饰的方法名会做为action动做名,与list、retrieve等同。
action装饰器能够接收两个参数:
methods: 该action支持的请求方式,列表传递
detail: 表示是action中要处理的是不是视图资源的对象(便是否经过url路径获取主键)
True 表示使用经过URL获取的主键对应的数据对象
False 表示不使用URL获取主键
路由Routers
对于视图集ViewSet,咱们除了能够本身手动指明请求方式与动做action之间的对应关系外,还可使用Routers来帮助咱们快速实现路由信息。
REST framework提供了两个router
SimpleRouter
DefaultRouter
1. 使用方法
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))
]
2. 视图集中包含附加action的
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
@action(methods=['get'], detail=False)
def latest(self, request):
...
@action(methods=['put'], detail=True)
def read(self, request, pk):
...
此视图集会造成的路由:
^books/latest/$ name: book-latest
^books/{pk}/read/$ name: book-read
其余功能
1. 认证Authentication
能够在配置文件中配置全局默认的认证方案
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 基本认证
'rest_framework.authentication.SessionAuthentication', # session认证
)
}
也能够在每一个视图中经过设置authentication_classess属性来设置
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = (SessionAuthentication, BasicAuthentication)
...
认证失败会有两种可能的返回值:
401 Unauthorized 未认证
403 Permission Denied 权限被禁止
2. 权限Permissions
权限控制能够限制用户对于视图的访问和对于具体数据对象的访问。
在执行视图的dispatch()方法前,会先进行视图访问权限的判断
在经过get_object()获取具体对象时,会进行对象访问权限的判断
使用
能够在配置文件中设置默认的权限管理类,如
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
若是未指明,则采用以下默认配置
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
也能够在具体的视图中经过permission_classes属性来设置,如
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
...
提供的权限
AllowAny 容许全部用户
IsAuthenticated 仅经过认证的用户
IsAdminUser 仅管理员用户
IsAuthenticatedOrReadOnly 认证的用户能够彻底操做,不然只能get读取
举例
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]
自定义权限
如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现如下两个任何一个方法或所有
.has_permission(self, request, view)
是否能够访问视图, view表示当前视图对象
.has_object_permission(self, request, view, obj)
是否能够访问数据对象, view表示当前视图, obj为数据对象
例如:
class MyPermission(BasePermission):
def has_object_permission(self, request, view, obj):
"""控制对obj对象的访问权限,此案例决绝全部对对象的访问"""
return False
class BookInfoViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
permission_classes = [IsAuthenticated, MyPermission]
限流Throttling
能够对接口访问的频次进行限制,以减轻服务器压力。
使用
能够在配置文件中,使用DEFAULT_THROTTLE_CLASSES 和 DEFAULT_THROTTLE_RATES进行全局配置,
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
DEFAULT_THROTTLE_RATES 可使用 second, minute, hour 或day来指明周期。
也能够在具体视图中经过throttle_classess属性来配置,如
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class ExampleView(APIView):
throttle_classes = (UserRateThrottle,)
...
可选限流类
1) AnonRateThrottle
限制全部匿名未认证用户,使用IP区分用户。
使用DEFAULT_THROTTLE_RATES['anon'] 来设置频次
2)UserRateThrottle
限制认证用户,使用User id 来区分。
使用DEFAULT_THROTTLE_RATES['user'] 来设置频次
3)ScopedRateThrottle
限制用户对于每一个视图的访问频次,使用ip或user id。
例如:
class ContactListView(APIView):
throttle_scope = 'contacts'
...
class ContactDetailView(APIView):
throttle_scope = 'contacts'
...
class UploadView(APIView):
throttle_scope = 'uploads'
...
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
过滤Filtering
对于列表数据可能须要根据字段进行过滤,咱们能够经过添加django-fitlter扩展来加强支持。
pip insall django-filter
在配置文件中增长过滤后端的设置:
INSTALLED_APPS = [
...
'django_filters', # 须要注册应用,
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
在视图中添加filter_fields属性,指定能够过滤的字段
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_fields = ('btitle', 'bread')
# 127.0.0.1:8000/books/?btitle=西游记
排序
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助咱们快速指明数据按照指定字段进行排序。
使用方法:
在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,若是包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
前端能够传递的ordering参数的可选字段值须要在ordering_fields中指明。
示例:
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_backends = [OrderingFilter]
ordering_fields = ('id', 'bread', 'bpub_date')
# 127.0.0.1:8000/books/?ordering=-bread
分页Pagination
REST framework提供了分页的支持。
咱们能够在配置文件中设置全局的分页方式,如:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每页数目
}
也可经过自定义Pagination类,来为视图添加不一样分页行为。在视图中经过pagination_clas属性来指明。
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
pagination_class = LargeResultsSetPagination
注意:若是在视图内关闭分页功能,只需在视图内设置
pagination_class = None
可选分页器
1) PageNumberPagination
前端访问网址形式:
GET http://api.example.org/books/?page=4
能够在子类中定义的属性:
page_size 每页数目
page_query_param 前端发送的页数关键字名,默认为"page"
page_size_query_param 前端发送的每页数目关键字名,默认为None
max_page_size 前端最多能设置的每页数量
from rest_framework.pagination import PageNumberPagination
class StandardPageNumberPagination(PageNumberPagination):
page_size_query_param = 'page_size'
max_page_size = 10
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = StandardPageNumberPagination
# 127.0.0.1/books/?page=1&page_size=2
2)LimitOffsetPagination
前端访问网址形式:
GET http://api.example.org/books/?limit=100&offset=400
能够在子类中定义的属性:
default_limit 默认限制,默认值与PAGE_SIZE设置一直
limit_query_param limit参数名,默认'limit'
offset_query_param offset参数名,默认'offset'
max_limit 最大limit限制,默认None
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
版本Versioning
REST framework提供了版本号的支持。
在须要获取请求的版本号时,能够经过request.version来获取。
默认版本功能未开启,request.version 返回None。
开启版本支持功能,须要在配置文件中设置DEFAULT_VERSIONING_CLASS
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning'
}
其余可选配置:
DEFAULT_VERSION 默认版本号,默认值为None
ALLOWED_VERSIONS 容许请求的版本号,默认值为None
VERSION_PARAM 识别版本号参数的名称,默认值为'version'
支持的版本处理方式
1) AcceptHeaderVersioning
请求头中传递的Accept携带version
GET /bookings/ HTTP/1.1
Host: example.com
Accept: application/json; version=1.0
2)URLPathVersioning
URL路径中携带
urlpatterns = [
url(
r'^(?P<version>(v1|v2))/bookings/$',
bookings_list,
name='bookings-list'
),
url(
r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$',
bookings_detail,
name='bookings-detail'
)
]
3)NamespaceVersioning
命名空间中定义
# bookings/urls.py
urlpatterns = [
url(r'^$', bookings_list, name='bookings-list'),
url(r'^(?P<pk>[0-9]+)/$', bookings_detail, name='bookings-detail')
]
# urls.py
urlpatterns = [
url(r'^v1/bookings/', include('bookings.urls', namespace='v1')),
url(r'^v2/bookings/', include('bookings.urls', namespace='v2'))
]
4)HostNameVersioning
主机域名携带
GET /bookings/ HTTP/1.1
Host: v1.example.com
Accept: application/json
5)QueryParameterVersioning
查询字符串携带
GET /something/?version=0.1 HTTP/1.1
Host: example.com
Accept: application/json
异常处理 Exceptions
REST framework提供了异常处理,咱们能够自定义异常处理函数。
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'
}
REST framework定义的异常
APIException 全部异常的父类
ParseError 解析错误
AuthenticationFailed 认证失败
NotAuthenticated 还没有认证
PermissionDenied 权限决绝
NotFound 未找到
MethodNotAllowed 请求方式不支持
NotAcceptable 要获取的数据格式不支持
Throttled 超过限流次数
ValidationError 校验失败
自动生成接口文档
REST framework能够自动帮助咱们生成接口文档。
接口文档以网页的方式呈现。
自动接口文档能生成的是继承自APIView及其子类的视图。
1. 安装依赖
REST framewrok生成接口文档须要coreapi库的支持。
pip install coreapi
2. 设置接口文档访问路径
在总路由中添加接口文档路径。
文档路由对应的视图配置为rest_framework.documentation.include_docs_urls,
参数title为接口文档网站的标题。
from rest_framework.documentation import include_docs_urls
urlpatterns = [
...
url(r'^docs/', include_docs_urls(title='My API title'))
]
3. 文档描述说明的定义位置
1) 单一方法的视图,可直接使用类视图的文档字符串,如
class BookListView(generics.ListAPIView):
"""
返回全部图书信息.
"""
2)包含多个方法的视图,在类视图的文档字符串中,分开方法定义,如
class BookListCreateView(generics.ListCreateAPIView):
"""
get:
返回全部图书信息.
post:
新建图书.
"""
3)对于视图集ViewSet,仍在类视图的文档字符串中封开定义,可是应使用action名称区分,如
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): """ list: 返回图书列表数据 retrieve: 返回图书详情数据 latest: 返回最新的图书数据 read: 修改图书的阅读量 """4. 访问接口文档网页浏览器访问 127.0.0.1:8000/docs/,便可看到自动生成的接口文档。--------------------- 做者:郭大帅 来源:CSDN 原文:https://blog.csdn.net/weixin_42225318/article/details/81433662 版权声明:本文为博主原创文章,转载请附上博文连接!