2个视图基类,5个视图扩展类,9个视图子类,视图集,drf自动生成路由

2021/7/2 23:26:33

本文主要是介绍2个视图基类,5个视图扩展类,9个视图子类,视图集,drf自动生成路由,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

两个视图基类

APIView

​
​

GenericAPIView

# 导入
from rest_framework.generics import GenericAPIView
​
​
类GenericView 继承了APIView,
​
class GenericAPIView(views.APIView):
    # 这里面定义了两个参数
    queryset = None
    serializer_class = None
    
    # 记住3个方法    
    def get_queryset(self)  # 获取所有数据,查询所有需要用到
    def get_object(self):   # 查询单个对象,需要用到
        
    def get_serializer(self, *args, **kwargs)
        ...
        return serializer_class(*args, **kwargs)# 使用这个方法得到序列化类的对象,可以传selif.get_serializer(instance,data,many)
    
    def get_serializer_class(self)
        ...
        return self.serializer_class
继承了GenericAPIView类的视图层类如下:
class BookGeneric(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializers
​
    # 查询所有
    def get(self,request,*args, **kwargs):
        obj_list = self.get_queryset()
        ser = self.get_serializer(obj_list, many=True)
        return Response(ser.data)
    
    def post(self,request,*args, **kwargs):
        pass
​
​
class BookDetailGeneric(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializers
​
    # 修改某一个
    def put(self, request, pk):
        obj = self.get_object().filter(pk=pk).first()
        ser = self.get_serializer(obj, data=request.data)
        return Response(ser.data)
    
    def get(self, request, pk):
        pass
    
    def delete(self, request,pk):
        pass

五个视图扩展类(没有继承其他类)

# 导入5个视图扩展类
# mixins.py
from rest_framework.mixins import CreateModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
# 查询所有,ListModelMixin,
# 新增 CreateModelMixin,
​
# 查询单个 RetrieveModelMixin
# 更新某个 UpdateModelMixin
# 删除某个 DestoryModelMixin
继承GenericAPIView类 和视图扩展类的视图类
# 当有了上面5个视图扩展类以后,就可以在我们自己写的视图类中自由组合的继承他们,实现不同的接口功能
# 记得这里写了一个小作业,继承GenericAPIView和一个自己写的类,在新建视图类中只配置那两个参数,即可实现5个接口
# 如下,为一个查询所有和新增的方法
class BookGenericList(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializers
​
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
​
    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

9个视图子类

现在,改写一下上述视图类,编写视图类继承视图子类实现同样的功能,并且实现了代码少量书写;

# 导入视图子类
# rest_framework.generics
​
from rest_framework.generics import ListAPIView,CreateAPIView,UpdateAPIView,DestroyAPIView,RetrieveAPIView
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView

视图类

# 此时我们只需要在自己写的视图类中继承视图子类ListCreateAPIView,就可以实现对数据的查询所有,和增加一条
class BookListCreate(ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializers
# 删除一条数据
class BookDestory(DestoryAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializers

视图集

可以看到视图类继承视图子类之后的视图类写法变简洁了,但是可以看见,上面两个视图类除了类名和继承的类不一样,下面的代码主体一样。使用视图集以后,能否将5个接口写在一个视图类中。请看下边

# 导入视图集类
from rest_framework.viewsets import ModelViewSet,GenericViewSet,ViewSetMixin,ReadOnlyModelViewSet,ViewSet
            

路由

    # 使用视图集的视图类的url
    path('bookviewset', views.BookViewSet.as_view({'get': 'list', 'post': 'create'})),
    path('bookdetailviewset/<int:pk>', views.BookViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))

实现5个接口的视图类

# 只继承了一个视图集ModelViewSet类就实现了5个接口的功能
class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializers

有点绕的东西

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    
from rest_framework.generics   
class GenericViewSet(ViewSetMixin, GenericAPIView):
    pass
​
# 还是要抓住那个cls,以及cls实例化出来的对象
class ViewSetMixin:
    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        """
        Because of the way class based views create a closure around the
        instantiated view, we need to totally reimplement `.as_view`,
        and slightly modify the view function that is created and returned.
        """
        # The name and description initkwargs may be explicitly overridden for
        # certain route configurations. eg, names of extra actions.
        cls.name = None
        cls.description = None
        cls.suffix = None
        cls.detail = None
        cls.basename = None
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r" % (
                    cls.__name__, key))
​
        # name and suffix are mutually exclusive
        if 'name' in initkwargs and 'suffix' in initkwargs:
            raise TypeError("%s() received both `name` and `suffix`, which are "
                            "mutually exclusive arguments." % (cls.__name__))
​
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
​
            if 'get' in actions and 'head' not in actions:
                actions['head'] = actions['get']
​
            # We also store the mapping of request methods to actions,
            # so that we can later set the action attribute.
            # eg. `self.action = 'list'` on an incoming GET request.
            self.action_map = actions
​
            # Bind methods to actions
            # This is the bit that's different to a standard view
            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)
​
            self.request = request
            self.args = args
            self.kwargs = kwargs
​
            # And continue as usual
            return self.dispatch(request, *args, **kwargs)
        
        # We need to set these on the view function, so that breadcrumb
        # generation can pick out these bits of information from a
        # resolved URL.
        view.cls = cls
        view.initkwargs = initkwargs
        view.actions = actions
        return csrf_exempt(view)
    ...
​
​

drf自动生成路由

# 导自动生成路由的类
from rest_framework.routers import Simplerouter
​
# 实例化得到对象
router = Simplerouter()
# 注册路由
router.register('路径',对应的自己写的视图类)
# 路由地址的列表
router.urls
# 与路由层的urlpatterns 进行拼接
urlpatterns += router.urls
​
还有一种写法
from django.urls import path,include
​
urlpatterns = [
    path('', include(router.urls)),
    # 也可以拼接路径
    path('api/v1/', include(router.urls)),
]
​
​





这篇关于2个视图基类,5个视图扩展类,9个视图子类,视图集,drf自动生成路由的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程