请求对象
REST框架引入了一个扩展了常规HttpRequest的请求对象, 并提供更灵活的请求解析。请求对象的核心功能是属性request.data,与request.POST类似,但对于WebAPIs更有用。
request.POST # Only handles form data. Only works for 'POST' method.
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
响应对象
REST framework还引入了一个响应对象,这是一种TemplateResponse类型,它接受未渲染的内容,并使用内容协商来确定返回给客户端的正确内容类型。
return Response(data) # Renders to content type as requested by the client.
状态码
在视图中使用数字HTTP状态码并不总是容易读懂,而且当使用了错误的状态码不容易发现。而REST框架为每个状态代码提供了更显式的标识符:
from rest_framework import status
drf中的函数视图
REST框架提供了一个装饰器@api_view,可以来装饰基本的函数视图。
这个装饰器提供了一些功能,比如确保在视图中接收到请求实例,并向响应对象添加上下文,以便可以执行内容协商。
装饰器还提供了一些行为,比如在适当的时候返回405 Method Not Allowed响应,以及处理当request.data输入不正确数据时发生的任何ParseError异常。
举例:
以前面创建过的序列化及项目为例,通过drf的函数视图来实现项目的增删改查
from project2s.serializers import ProjectSerializers
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['GET', 'POST'])
def list_create(request):
“”“”查询或创建方法“”“
if request.method == 'GET':
s = Student.objects.all() # 查询集
ser = ProjectSerializers(s, many=True) #序列化器
return Response(ser.data)
elif request.method == 'POST':
ser = ProjectSerializers(request.data)
if ser.is_valid():
ser.save()
return Response(ser.data, status=status.HTTP_201_CREATED)
else:
return JsonResponse(ser.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def update_detail_delete(request, pk):
try:
obj = Student.objects.get(pk=pk)
except Student.DoesNotExist:
return Response(status=status.HTTP_400_BAD_REQUEST)
if request.method == 'GET':
ser = ProjectSerializers(obj)
return Response(ser.data)
elif request.method == 'PUT':
ser = ProjectSerializers(obj, request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
obj.delete()
return JsonResponse({'message': '删除成功'}, status=status.HTTP_204_NO_CONTENT)
请求结果:
配置url可选格式后缀
可以通过添加格式后缀返回对应格式的内容
http http://127.0.0.1:8000/student.json # JSON suffix
http http://127.0.0.1:8000/student.api # Browsable API suffix
导入 format_suffix_patterns处理下路由
from django.urls import path
from project2s import views
from rest_framework.urlpatterns import format_suffix_patterns
app_name = 'project2s'
urlpatterns = [
path('students/', views.list_create), # 创建或展示
path('students/<int:pk>/', views.update_detail_delete) # 删除或显示
]
urlpatterns = format_suffix_patterns(urlpatterns)
views.py中的视图函数需要加上format=None参数
当我们配置处理这个路由之后,当直接使用浏览器访问接口时,它会返回该资源的html格式表示。
http http://127.0.0.1:8000/student.api :
http http://127.0.0.1:8000/student.json:
drf中的类视图
编写类视图继承APIView基类:
from django.http import Http404
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from project2s.serializers import ProjectSerializers
from project2s.models import Student
#类视图
class ListCreateView(APIView):
def get(self, request, format=None):
obj = Student.objects.all()
ser = ProjectSerializers(obj, many=True)
return Response(ser.data)
def post(self, request, format=None):
ser = ProjectSerializers(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data, status=status.HTTP_201_CREATED)
else:
return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST)
class UpdatePutDeleteDetailView(APIView):
def get_object(self, pk):
try:
return Student.objects.get(pk=pk)
except Student.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
obj = self.get_object(pk)
ser = ProjectSerializers(obj)
return Response(ser.data)
def put(self, request, pk, format=None):
obj = self.get_object(pk)
ser = ProjectSerializers(obj, data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data, status=status.HTTP_204_NO_CONTENT)
return Response(ser.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
self.get_object(pk).delete()
return Response(status=status.HTTP_204_NO_CONTENT)
基于类的视图重写API
当有多个模型需要编写类视图,由上可见代码部分可复用,而drf框架提供了很多基类进行了高度封装,只需要继承即可。
from rest_framework import generics, mixins
generics中提供了获取模型对象及序列化器的类,需要通过queryset,serializer_class指定:
mixins中封装好的类如下:
创建:
获取:
更新:
删除:
通过视图类继承这些类并调用其中方法即可:
from rest_framework import generics, mixins
from project2s.models import Student
from project2s.serializers import ProjectSerializers
# 类视图
class ListCreateView(generics.GenericAPIView,
mixins.ListModelMixin,
mixins.CreateModelMixin):
queryset = Student.objects.all()
serializer_class = ProjectSerializers
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) # 调用ListModelMixin类中的self.list()
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs) # 调用CreateModelMixin类中的self.create()
class UpdatePutDeleteDetailView(generics.GenericAPIView,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin):
queryset = Student.objects.all()
serializer_class = ProjectSerializers
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs) # 调用RetrieveModelMixin类中的self.retrieve()
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) # 调用UpdateModelMixin类中的self.update()
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs) # 调用DestroyModelMixin类中的self.destroy()
还没结束,以上编写的继承关系在generics类中其实已经封装好了,如下:
所以只需要继承generics中的类即可:
from project2s.models import Student
from project2s.serializers import ProjectSerializers
from rest_framework import status, generics, mixins
# 类视图
class ListCreateView(generics.ListCreateAPIView):
queryset = Student.objects.all()
serializer_class = ProjectSerializers
class UpdatePutDeleteDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Student.objects.all()
serializer_class = ProjectSerializers
访问结果: