rest-framework之视图

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方法对应如下:

image


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


执行数据库迁移命令;

插入数据:

image


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创建:

image


get获取:

image


put更新:

image


delete删除:

image


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。
原文地址:https://www.cnblogs.com/weiyiming007/p/12517650.html