1、DRF中的Request
在Django REST Framework中内置的Request类扩展了Django中的Request类,实现了很多方便的功能--如请求数据解析和认证等。
比如,区别于Django中的request从request.GET中获取URL参数,从request.POST中取某些情况下的POST数据。
在APIView中封装的request,就实现了请求数据的解析:
对于GET请求的参数我们通过request.query_params来获取。
对于POST请求、PUT请求的数据我们通过request.data来获取。
在from rest_framework import viewsets
这个viewset中,有5类Minxin,他们与http方法对应如下:
2、基本视图之初学乍练
写一个出版社的增删查改resful接口:
urls.py
url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P<pk>d+)/$', views.PublishDetailView.as_view()),
views.py,因为获取(get)一个和获取(get)多个会有冲突,所以要写两个接口类
class PublishSerializers(serializers.ModelSerializer): class Meta: model=models.Publish fields='__all__' class PublishView(APIView): def get(self, request): publish_list = models.Publish.objects.all() bs = PublishSerializers(publish_list, many=True) # 序列化数据 return Response(bs.data) def post(self, request): # 添加一条数据 print(request.data) bs=PublishSerializers(data=request.data) if bs.is_valid(): bs.save() # 生成记录 return Response(bs.data) else: return Response(bs.errors) class PublishDetailView(APIView): def get(self,request,pk): publish_obj=models.Publish.objects.filter(pk=pk).first() bs=PublishSerializers(publish_obj,many=False) return Response(bs.data) def put(self,request,pk): publish_obj = models.Publish.objects.filter(pk=pk).first() bs=PublishSerializers(data=request.data,instance=publish_obj) if bs.is_valid(): bs.save() # update return Response(bs.data) else: return Response(bs.errors) def delete(self,request,pk): models.Publish.objects.filter(pk=pk).delete() return Response("")
models.py参考下面的;
3、mixin类和generice类编写视图之上层武功
settings.py
INSTALLED_APPS = [ ... 'rest_framework', ]
models.py
from django.db import models # Create your models here. class Book(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish_date = models.DateField(null=True) xx=models.IntegerField(choices=((0,'文学类'),(1,'情感类')),default=1,null=True) publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE,null=True) authors=models.ManyToManyField(to='Author') def __str__(self): return self.name def test(self): return 'xxx' class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name
执行数据库迁移命令;
插入数据:
views.py
from django.shortcuts import render from rest_framework.views import APIView from rest_framework import serializers from app01 import models from rest_framework.response import Response # Create your views here. # 基于mixins来封装的视图 from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin from rest_framework.generics import GenericAPIView class PublishView(CreateModelMixin, ListModelMixin, GenericAPIView): queryset = models.Publish.objects.all() serializer_class = PublishSerializers def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) class PublishDetailView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView): queryset = models.Publish.objects.all() serializer_class = PublishSerializers 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)
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P<pk>d+)/$', views.PublishDetailView.as_view()), ]
用postman测试:
post创建:
get获取:
put更新:
delete删除:
4、使用generics 下ListCreateAPIView, RetrieveUpdateDestroyAPIView之高深武功
models.py urls.py和上面都一样;
views.py
from django.shortcuts import render from rest_framework.views import APIView from rest_framework import serializers from app01 import models from rest_framework.response import Response from rest_framework import viewsets class PublishSerializers(serializers.ModelSerializer): class Meta: model=models.Publish fields='__all__' # 第三种写法 from rest_framework.generics import CreateAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView class PublishView(ListCreateAPIView): queryset=models.Publish.objects.all() serializer_class = PublishSerializers class PublishDetailView(RetrieveUpdateDestroyAPIView): queryset=models.Publish.objects.all() serializer_class = PublishSerializers
5、使用ModelViewSet 之终极大法
urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), # url(r'^publish/$', views.PublishView.as_view()), # url(r'^publish/(?P<pk>d+)/$', views.PublishDetailView.as_view()), url(r'^publish/$', views.PublishView.as_view({'get': 'list', 'post': 'create'})), url(r'^publish/(?P<pk>d+)/$',views.PublishView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})), ]
views.py
from rest_framework.viewsets import ModelViewSet class PublishView(ModelViewSet): queryset=models.Publish.objects.all() serializer_class=PublishSerializers
6、扩展
a、如果有的功能不能满足开发需求时,可以重新一些方法;
b、继承ViewSetMixin 改写路由与视图
views.py
from rest_framework.viewsets import ViewSetMixin from rest_framework.views import APIView # ViewSetMixin重写了as_view方法 # 我们可以写一个类继承ViewSetMixin,和APIView,要保证这种继承顺序
# 写一个aaa方法,(可以写多个不同的方法) class Test(ViewSetMixin, APIView): def aaa(self, request): return Response()
def bbb(self, request):
return Response()
urls.py
# 此时路由中就可以这样写了,当有get请求时就会走我们在views.py中定义的aaa方法 url(r'^aa/$', views.PublishView.as_view({'get': 'aaa', })),
# 访问bb路径时,get请求时就会走我们在views.py中定义的bbb方法
url(r'^bb/$', views.PublishView.as_view({'get': 'bbb', })),
7、视图组件总结
1)DRF所有视图文件
所有的视图类在如下这四个文件内:
from rest_framework import views # APIView from rest_framework import generics # 公共通用视图类:GenericAPIView,及各种组合视图类CreateAPIView、ListAPIView、RetrieveAPIView等 from rest_framework import mixins # 混合继承类:CreateModelMixin、ListModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin from rest_framework import viewsets # 重写as_view: ViewSetMixin;其他类都是帮助去继承ViewSetMixin
2)DRF视图图谱
视图类继承顺序,如下图所示:
说明:
1、首先 django是继承 view的,DRF是从APIView开始继承起,APIView封装了request,其中包含了data、query_params等属性、方法。 2、然后 GenericAPIView封装了 get_queryset() 和 get_serializer();ViewSetMixin重写了 as_view()方法。 3、随后 GenericViewSet继承GenericAPIView和ViewSetMixin。 4、最后最高层的封装是 ModelViewSet。