请求和响应
请求对象(Request objects)拓展了Django自带的HttpRequest
- REST框架引入了一个扩展了常规HttpRequest的Request对象,并提供了更灵活的请求解析。Request对象的核心功能是request.data属性,它与request.POST类似,但对于使用Web API更为有用
request.POST
- 只处理表单数据 只适用于'POST'方法
request.data
- 处理任意数据 适用于'POST','PUT'和'PATCH'方法
响应对象(Response objects)
- REST框架还引入了一个Response对象,这是一种获取未渲染(unrendered)内容的TemplateResponse类型,并使用内容协商来确定返回给客户端的正确内容类型
return Response(data)
- 渲染成客户端请求的内容类型。
状态码(Status codes)
- 在你的视图(views)中使用纯数字的HTTP 状态码并不总是那么容易被理解。而且如果错误代码出错,很容易被忽略。REST框架为status模块中的每个状态代码(如HTTP_400_BAD_REQUEST)提供更明确的标识符。使用它们来代替纯数字的HTTP状态码是个很好的主意。
包装(wrapping)API视图
- REST框架提供了两个可用于编写API视图的包装器(wrappers)
- 用于基于函数视图的@api_view装饰器。
- 用于基于类视图的APIView类。
这些包装器提供了一些功能,例如确保你在视图中接收到Request实例,并将上下文添加到Response,以便可以执行内容协商。
包装器还提供了诸如在适当时候返回405 Method Not Allowed响应,并处理在使用格式错误的输入来访问request.data时发生的任何ParseError异常。
应用
导入模块
from .models import Publisher
from rest_framework.decorators import api_view
from app01 import serializers
from rest_framework.response import Response
编写视图
GET
from .models import Publisher
from rest_framework.decorators import api_view
from app01 import serializers
from rest_framework.response import Response
# 列表里面的参数是被允许的操作,比如只有GET/POST请求,如果不是get或者post会报405--->405 Method Not Allowed
@api_view(['GET', 'POST'])
def publisher_list(request):
"""
列出所有出版社,get
或者创建一个新的出版社 post
"""
if request.method == 'GET':
# 所有的出版社
queryset = Publisher.objects.all()
# 把所有从数据库取出来的出版社信息数据进行序列化
s = serializers.PublisherSerializer(queryset, many=True)
return Response(s.data)
获取、更新或者删除一个(单个)出版社信息
GET
# GET 获取出版社
@api_view(['GET', 'PUT', 'DELETE'])
def publisher_detail(request, pk):
try:
# 从数据库里面找你要找的pk
publisher = Publisher.objects.get(pk=pk)
except Publisher.DoesNotExist: # 如果找不到浏览器传来的pk对应的数据,返回404
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
# 从数据库里面取出来的publisher进行序列化
s = serializers.PublisherSerializer(publisher)
return Response(s.data)
POST
if request.method == 'PUT':
# publisher使我们查出来的出版社信息 request.data是客户端传过来的
s = serializers.PublisherSerializer(publisher, data=request.data)
if s.is_valid():# 如果数据没有问题
s.save()
return Response(s.data)
else:
return Response(status=status.HTTP_204_NO_CONTENT)
DELETE
if request.method == 'DELETE':
publisher.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
给我们的网址添加可选的格式后缀
- 为了充分利用我们的响应不再与单一内容类型连接,我们可以为API路径添加对格式后缀的支持。使用格式后缀给我们明确指定了给定格式的URL,这意味着我们的API将能够处理诸如
-
http:/\/example.com/api/items/4.json
之类的URL。
设置路由
url(r'^publishers/(?P<pk>[0-9]+)/$', views.publisher_detail)
刷新浏览器
创建一个账号
- 接下来我们可以通过两种方式访问
方式一: httpie
pip install httpie
- 然后在命令行访问
方式二:(调出登录)
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
基于类的视图(CBV)
导入模块
from rest_framework.views import APIView
GET
from .models import Publisher
from app01 import serializers
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
class PublisherList(APIView):
"""列出所有的出版,get或者创建一个新的出版社post"""
def get(self, request, format=None):
queryset = Publisher.objects.all() # 查询出所有出版社
s = serializers.PublisherSerializer(queryset, many=True)
return Response(s.data, status=status.HTTP_200_OK)
POST
def post(self,request,format=None):
s = serializers.PublisherSerializer(data=request.data)
if s.is_valid():
s.save()
return Response(s.data,status=status.HTTP_201_CREATED)
else:
return Response(s.errors,status=status.HTTP_400_BAD_REQUEST)
具体的某一个出版社CBV
class PublisherDetail(APIView):
"""具体的某一个出版社 查看.修改.删除的视图"""
# 需要先尝试的从数据库查到 pk对应的数据,如果没有返回404
def get_object(self, pk):
try:
return Publisher.objects.get(pk=pk)
except Publisher.DoesNotExist:
raise Http404 # 需要先导入 from django.http import Http404
GET 获取出版社信息(单个)
def get(self, request, pk, format=None):
publisher = self.get_object(pk)
s = serializers.PublisherSerializer(publisher)
return Response(s.data, status=status.HTTP_200_OK)
PUT 修改出版社信息(单个)
def put(self, request, pk, format=None):
publisher = self.get_object(pk)
s = serializers.PublisherSerializer(publisher, data=request.data)
if s.is_valid():
s.save()
return Response(s.data)
else:
Response(s.errors, status=status.HTTP_400_BAD_REQUEST)
DELETE 删除出版社信息(单个)
def delete(self, request, pk, format=None):
"""删除出版社信息"""
publisher = self.get_object(pk)
publisher.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
修改url
url(r'^publishers/$', views.PublisherList.as_view()),
url(r'^publishers/(?P<pk>[0-9]+)/$', views.PublisherDetail.as_view()),
使用混合(mixins)
- 使用基于类视图的最大优势之一是它可以轻松地创建可复用的行为。
- 到目前为止,我们使用的创建/获取/更新/删除操作和我们创建的任何基于模型的API视图非常相似。这些常见的行为是在REST框架的mixin类中实现的。
导入模块
from rest_framework import mixins
from rest_framework import generics
编写视图
from rest_framework import mixins
from rest_framework import generics
class PublisherList(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
queryset = Publisher.objects.all()
serializers_class = serializers.PublisherSerializer
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 PublisherDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Publisher.objects.all()
serializer_class = serializers.PublisherSerializer
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)
- 刷新浏览器
改进混合视图
class PublisherList(generics.ListCreateAPIView):
queryset = Publisher.objects.all()
serializer_class = serializers.PublisherSerializer
class PublisherDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Publisher.objects.all()
serializer_class = serializers.PublisherSerializer
刷新浏览器
-
此时我们观察,代码已经精简至3行
官方文档一句话说的非常好:仅仅只需要很少的几行代码,就可以完成非常清晰,简洁,地道的Django