请求request方法
请求解析
.data
request.data 返回请求的的正文的解析内容,类似于标准reques.POST 和request.FILES
- 它包括所有已解析的内容,包括文件和非文件的输入
- 它支持解析除以外的http方法的内容,可以获取PUT 和PACTH 请求的内容
- 可以处理传入的表单数据, 也可以处理传入的json数据
.query_params
- 相当于request.GET
.parsers
认证方式
- 对API的不同部分使用不同的身份验证策略
- 支持使用多种身份验证策略
- 提供与传入请求关联的用户和令牌信息
与用户相关
.user
request.user 通常返回实例,django.contrib.auth.models.User ,如果身份未经验证,则返回django.contrib.auth.models.AnonymousUser
.auth
返回任何其他身份验证上下文,如果改请求未认证,返回None
.authenticators
在视图里面使用authentication_classes,或者在settings文件里面使用DEFAULT_AUTHENTICATORS
响应 responses
Response()
- from rest_framework.response import Response
- Response(data, status=None, template_name=None, headers=None, content_type=None)
- Response 无法处理实例类,因此需要在创建Response 对象之前将数据序列化为原始数据类型
- 可以使用REST框架的 Serializer类来进行数据序列化
参数: - data:响应的序列化数据
- status:响应的状态吗
- template_name:使用了HTMLRenderer或其使用他自定义模板渲染器时才需要
- headers :在响应中使用的HTTP标头字典
- content_type:响应的内容类型
HttpResponse属性
你可以在响应中设置标头如:
response = Response()
response['Cache-Control'] = 'no-cache'
基于类的视图View
APIview
- from rest_framework.views import APIView
- 基础了Django 的View类,但也与View有所不同
- 传递给除了程序方法的请求将是REST框架的Request实例,而不是django的HttpRequest 实例
- 处理程序方法可能返回REST框架的Response而不是Django的HttpResponse。该视图将管理内容协商并在响应上设置正确的渲染器。
- 任何APIException异常都将被捕获并调解为适当的响应。
- 在将请求分派到处理程序方法之前,将对传入的请求进行身份验证并进行适当的权限和/或限制检查。
例如:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions
from django.contrib.auth.models import User
class ListUsers(APIView):
"""
View to list all users in the system.
* Requires token authentication.
* Only admin users are able to access this view.
"""
authentication_classes = [authentication.TokenAuthentication]
permission_classes = [permissions.IsAdminUser]
def get(self, request, format=None):
"""
Return a list of all users.
"""
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
通用视图 Generic views
它的主要优点之一是它们允许你组成一些可重用行为的方式,
例子
通常,在使用通用视图时,你要写这几个属性
- queryset
- serializer_class
- permission_classes
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAdminUser]
对于复杂情况,你还可以覆盖视图类里面的方法
generics.ListCreateAPIView 可以覆盖list 方法
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [IsAdminUser]
def list(self, request):
# Note the use of `get_queryset()` instead of `self.queryset`
queryset = self.get_queryset()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
GenericAPIView
-
该类扩展了REST框架的APIView类,为标准列表和详细信息视图添加了通常需要的行为。
-
提供的每个具体的通用视图都是通过将GenericAPIView,和一个或多个mixin类组
合而构建的。
属性
- queryset-应该用于从该视图返回对象的查询集。通常,您必须设置此属性或重写get_queryset()方法。如果要覆盖视图方法,则必须进行调用get_queryset()而不是直接访问此属性,这queryset将被评估一次,并且这些结果将被缓存用于所有后续请求,这一点很重要。
- serializer_class-应该用于验证和反序列化输入以及序列化输出的序列化器类。通常,您必须设置此属性或重写get_serializer_class()方法。
- lookup_field-应该用于执行单个模型实例的对象查找的模型字段。默认为’pk’。请注意,使用超链接的API时,您需要确保双方的API意见和串行类设置查找字段,如果你需要使用一个自定义值。
- lookup_url_kwarg-用于对象查找的URL关键字参数。URL conf应包含与此值相对应的关键字参数。如果未设置,则默认使用与相同的值lookup_field。
分页:
与列表视图一起使用时,以下属性用于控制分页。
-
pagination_class-对列表进行分页时应使用的分页类。默认值为与DEFAULT_PAGINATION_CLASS设置相同的值’rest_framework.pagination.PageNumberPagination’。设置pagination_class=None将禁用此视图上的分页。
筛选: -
filter_backends-应该用于过滤查询集的过滤器后端类的列表。默认值为与DEFAULT_FILTER_BACKENDS设置相同的值。
方法
基本方法:
get_queryset(self)
-
返回应用于列表视图的查询集,该查询集应用作详细视图中的查询的基础。默认情况下返回queryset属性指定的查询集。
-
应始终使用此方法,而不是self.queryset直接访问此方法,因为它self.queryset只会被评估一次,并且那些结果将为所有后续请求缓存。
-
可以重写以提供动态行为,例如返回特定于发出请求的用户的查询集。
例如:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
get_object(self)
- 返回应用于详细信息视图的对象实例,默认使用lookup_field 参数过滤基本查询集,可以重写以提供更复杂的行为,例如基于多个URL kwarg的对象查找
例如:
def get_object(self):
queryset = self.get_queryset()
filter = {}
for field in self.multiple_lookup_fields:
filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter)
self.check_object_permissions(self.request, obj)
return obj
请注意,如果您的API不包含任何对象级别的权限,则可以选择排除self.check_object_permissions,而只需从get_object_or_404查找中返回对象即可
mixin 类
mixin类可以从导入rest_framework.mixins
ListModelMixin
-
提供一种.list(request, *args, **kwargs)方法,该方法实现列出查询集。
-
如果填充了查询集,则返回一个200 OK响应,并将查询集的序列化表示形式作为响应的主体。可以可选地对响应数据进行分页。
CreateModelMixin
-
提供一种.create(request, *args, **kwargs)方法,该方法实现创建和保存新模型实例。
-
如果创建了对象,则返回一个201 Created响应,该对象的序列化表示作为响应的主体。如果表示形式包含名为的键url,则将Location使用该值填充响应的标头。
-
如果提供的用于创建对象的请求数据无效,400 Bad Request则将返回响应,并将错误详细信息作为响应的正文。
RetrieveModelMixin
-
提供一种.retrieve(request, *args, **kwargs)方法,该方法实现在响应中返回现有模型实例。
-
如果可以检索到对象,则返回一个200 OK响应,该对象的序列化表示作为响应的主体。否则将返回404 Not Found。
UpdateModelMixin
-
提供一种.update(request, *args, **kwargs)方法,该方法实现更新和保存现有模型实例。
-
还提供了一种.partial_update(request, *args, **kwargs)方法,该方法与该update方法类似,但是用于更新的所有字段都是可选的。这样可以支持HTTP PATCH请求。
-
如果对象被更新,它将返回一个200 OK响应,该对象的序列化表示作为响应的主体。
-
如果提供的用于更新对象的请求数据无效,400 Bad Request则将返回响应,并将错误详细信息作为响应的主体
DestroyModelMixin
-
提供一种.destroy(request, *args, **kwargs)方法,该方法实现删除现有模型实例。
-
如果删除对象,则返回204 No Content响应,否则将返回404 Not Found。
自定义通用视图
例如,如果您需要基于URL conf中的多个字段查找对象,则可以创建如下的mixin类:
class MultipleFieldLookupMixin(object):
"""
Apply this mixin to any view or viewset to get multiple field filtering
based on a `lookup_fields` attribute, instead of the default single field filtering.
"""
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
filter = {}
for field in self.lookup_fields:
if self.kwargs[field]: # Ignore empty fields.
filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj
然后,您可以在需要应用自定义行为的任何时间简单地将此混入应用于视图或视图集。
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_fields = ['account', 'username']
具体的视图类
以下类是具体的通用视图。如果您使用的是通用视图,那么通常这就是您要使用的级别,除非需要大量的自定义行为。
可以从中导入视图类rest_framework.generics。
CreateAPIView
-
用于仅创建端点。
-
提供post方法处理程序。
扩展:GenericAPIView,CreateModelMixin
ListAPIView
-
用于只读端点,表示模型实例的集合。
-
提供get方法处理程序。
扩展:GenericAPIView,ListModelMixin
检索APIView
-
用于只读端点,以表示单个模型实例。
-
提供get方法处理程序。
扩展:GenericAPIView,RetrieveModelMixin
销毁APIView
-
用于单个模型实例的仅删除端点。
-
提供delete方法处理程序。
扩展:GenericAPIView,DestroyModelMixin
UpdateAPIView
-
用于单个模型实例的仅更新端点。
-
提供put和patch方法处理程序。
扩展:GenericAPIView,UpdateModelMixin
ListCreateAPIView
-
用于读写端点,表示模型实例的集合。
-
提供get和post方法处理程序。
扩展:GenericAPIView,ListModelMixin,CreateModelMixin
RetrieveUpdateAPIView
-
用于读取或更新端点以表示单个模型实例。
-
提供get,put并且patch方法处理。
扩展:GenericAPIView,RetrieveModelMixin,UpdateModelMixin
RetrieveDestroyAPIView
-
用于读取或删除端点,以表示单个模型实例。
-
提供get和delete方法处理程序。
扩展:GenericAPIView,RetrieveModelMixin,DestroyModelMixin
RetrieveUpdateDestroyAPIView
-
用于读写删除端点,以表示单个模型实例。
-
提供get,put,patch和delete方法处理。
扩展:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
视图集
ViewSets
-
ViewSet 类只是一种类型的基于类的视图,不提供任何方法的处理程序,例如.get() .post 而是提供操作,如.list() 和.create()
-
使用方法,a的方法处理程序ViewSet仅在完成视图时绑定到相应的动作.as_view()。
-
通常,您将向路由器集注册视图集,而不是在urlconf中的视图集中显式注册视图,而是自动为您确定urlconf
例
- 让我们定义一个简单的视图集,可用于列出或检索系统中的所有用户。
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response
class UserViewSet(viewsets.ViewSet):
"""
A simple ViewSet for listing or retrieving users.
"""
def list(self, request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)
如果需要,可以将此视图集绑定到两个单独的视图中,如下所示:
user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})
通常,我们不这样做,而是向路由器注册视图集,并允许自动生成urlconf。
from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
urlpatterns = router.urls
您通常不希望编写自己的视图集,而是要使用提供默认行为集的现有基类。例如:
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
serializer_class = UserSerializer
queryset = User.objects.all()
-
使用类有两个主要优点View。
-
重复的逻辑可以合并为一个类。在上面的示例中,我们只需要指定queryset一次,它将在多个视图中使用。
-
通过使用路由器,我们不再需要自己处理URL conf。
-
两者都需要权衡。使用常规视图和URL conf更加明确,并给您更多的控制权。如果您想快速启动并运行,或者当您使用大型API并希望在整个过程中实施一致的URL配置,则ViewSets很有帮助。
ViewSet操作
- REST框架随附的默认路由器将为一组标准的创建/检索/更新/销毁样式操作提供路由,如下所示:
class UserViewSet(viewsets.ViewSet):
"""
Example empty viewset demonstrating the standard
actions that will be handled by a router class.
If you're using format suffixes, make sure to also include
the `format=None` keyword argument for each action.
"""
def list(self, request):
pass
def create(self, request):
pass
def retrieve(self, request, pk=None):
pass
def update(self, request, pk=None):
pass
def partial_update(self, request, pk=None):
pass
def destroy(self, request, pk=None):
pass
Routers
SimpleRouter
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = router.urls
该方法有两个强制性参数register()
- prefix 用于这组路由URL前缀
- viewset 视图集类
- (可选)你还可以指定其他参数
- basename 用于创建URL名称,如果未设置,则名称将基于queryset视图集的属性自动生成,如果视图集不包含queryset属性,则必须basename在注册视图集市进行设置
- 上面的示例将生成以下URL模式:
- 网址格式:^user/$ 名称:‘user-list’
- 网址格式:^user/{pk}/$ 名称:‘user-detail’
- 网址格式:^accounts/$ 名称:‘account-list’
- 网址格式:^accounts/{pk}/$ 名称:‘account_detail’
注意:该basename 参数用于指定视图名称模式的初始部分,通常,你不需要指定basename参数,但如果你有一个定义了自定义get_queryset 方法的视图,则该视图可能没有属性集,如果尝试注册该视图集,则会看到类似的错误
'basename' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
这意味着basename注册视图集时需要显式设置参数,因为无法从模型名称自动确定该参数。
include与路由器一起使用
-
.urls路由器实例上的属性只是URL模式的标准列表。关于如何包含这些URL,有很多不同的样式。
-
例如,您可以追加router.urls到现有视图的列表中…
router = routers.SimpleRouter()
router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet)
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
]
urlpatterns += router.urls
另外,你也可以使用diango的include功能例如
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^', include(router.urls)),
]
- 您可以使用include应用程序名称空间:
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^api/', include((router.urls, 'app_name'))),
]
- 或应用程序和实例名称空间:
urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
url(r'^api/', include((router.urls, 'app_name'), namespace='instance_name')),
]
注意:如果将命名空间与超链接的序列化程序一起使用,则还需要确保view_name序列化程序上的所有参数都能正确反映名称空间。在上面的示例中,您需要包括一个参数,例如view_name='app_name:user-detail’超链接到用户详细信息视图的序列化程序字段的参数 。
自动view_name生成使用的模式%(model_name)-detail。除非您的模型名称实际发生冲突,否则在使用超链接序列化程序时最好不要为 Django REST Framework视图命名。
Parsers 解析器
如何确定解析器
当request.data 被访问时,REST框架将检测Content-Type传入请求上的标头,并确定使用那个解析器来解析请求内容
注意:开发客户端应用时,切记要确保Content_Type 在HTTP请求中发送数据时设置头,如果你没有设置内容内心,则大多数客户端将默认使用"applixation/x-www-form-urlencoded",如果要使用jquery 和ajax() 方法发送json数据时,则应确保包括该ContentType:‘application/json’
设置解析器
- 可以使用DEFAULT_PARSER_CLASSES 设置全局默认解析器,例如,以下设置将允许带有json内容的请求,而不是默认的json或表单数据
REST_FRAMEWORK = {
‘DEFAULT_PARSER_CLASSES’:{
‘rest_framework.parsers.JSONParser’,
}
} - 你还可以使用APIView基于类的视图来设置用于单个视图或视图集的解析器
在类使用parser_classes 属性
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
"""
A view that can accept POST requests with JSON content.
"""
parser_classes = [JSONParser]
def post(self, request, format=None):
return Response({'received data': request.data})
JSONParser
- 解析json请求内容
- .media_type:application/json
FormParser
- 解析HTML表单内容。
- .media_type:application/x-www-form-urlencoded
MulitiPartParser
- 解析多个HTML表单内容,支持文件上传
- .media_type: multipart/form-data
FileUploadParser
-
解析原始文件上传内容。该request.data属性将是一个字典,'file’其中包含包含上载文件的单个键。
-
如果通过URL关键字参数FileUploadParser调用与with一起使用的视图filename,则该参数将用作文件名。
-
如果在没有filenameURL关键字参数的情况下调用它,则客户端必须在Content-DispositionHTTP标头中设置文件名。例如Content-Disposition: attachment; filename=upload.jpg。
-
.media_type:/
笔记: -
的FileUploadParser是与本地客户端的使用,可以将文件上传的原始数据请求。对于基于网络的上传,或与多上传支持本地客户端,您应该使用MultiPartParser来代替。
-
由于该解析器的media_type任何内容类型相匹配,FileUploadParser一般应在API视图设置的唯一的解析器。
-
FileUploadParser尊重Django的标准FILE_UPLOAD_HANDLERS设置和request.upload_handlers属性。有关更多详细信息,
用法示例:
# views.py
class FileUploadView(views.APIView):
parser_classes = [FileUploadParser]
def put(self, request, filename, format=None):
file_obj = request.data['file']
# ...
# do some stuff with uploaded file
# ...
return Response(status=204)
# urls.py
urlpatterns = [
# ...
url(r'^upload/(?P<filename>[^/]+)$', FileUploadView.as_view())
]
自定义解析器
-
要实现自定义解析器,应重写BaseParser,设置.media_type属性并实现.parse(self, stream, media_type, parser_context)方法。
-
该方法应返回将用于填充request.data属性的数据。
-
传递给的参数.parse()是:stream
媒体类型
-
可选的。如果提供,这是传入请求内容的媒体类型。
-
根据请求的Content-Type:标头,它可能比渲染器的media_type属性更具体,并且可能包括媒体类型参数。例如"text/plain; charset=utf-8"。
parser_context
-
可选的。如果提供,则此参数将是一个字典,其中包含解析请求内容可能需要的任何其他上下文。
-
默认情况下,这将包括以下键:view,request,args,kwargs。
例
class PlainTextParser(BaseParser):
"""
Plain text parser.
"""
media_type = 'text/plain'
def parse(self, stream, media_type=None, parser_context=None):
"""
Simply return a string representing the body of the request.
"""
return stream.read()