Django高级进阶[DRF](3. 简化

请求和响应

请求对象(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)
    1. 用于基于函数视图的@api_view装饰器。
    1. 用于基于类视图的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[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[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

你可能感兴趣的:(Django高级进阶[DRF](3. 简化)