视图组件

9个视图子类

  1'''
29个视图子类
3from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView, UpdateAPIView, DestroyAPIView,RetrieveAPIView,RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
4'''

5
6class CreateAPIView(mixins.CreateModelMixin,  # mixins是一个py文件
7                    GenericAPIView)
:

8    """
9    Concrete view for creating a model instance.
10    """

11    def post(self, request, *args, **kwargs):
12        return self.create(request, *args, **kwargs)
13
14
15class ListAPIView(mixins.ListModelMixin,
16                  GenericAPIView)
:

17    """
18    Concrete view for listing a queryset.
19    """

20    def get(self, request, *args, **kwargs):
21        return self.list(request, *args, **kwargs)
22
23
24class RetrieveAPIView(mixins.RetrieveModelMixin,
25                      GenericAPIView)
:

26    """
27    Concrete view for retrieving a model instance.
28    """

29    def get(self, request, *args, **kwargs):
30        return self.retrieve(request, *args, **kwargs)
31
32
33class DestroyAPIView(mixins.DestroyModelMixin,
34                     GenericAPIView)
:

35    """
36    Concrete view for deleting a model instance.
37    """

38    def delete(self, request, *args, **kwargs):
39        return self.destroy(request, *args, **kwargs)
40
41
42class UpdateAPIView(mixins.UpdateModelMixin,
43                    GenericAPIView)
:

44    """
45    Concrete view for updating a model instance.
46    """

47    def put(self, request, *args, **kwargs):
48        return self.update(request, *args, **kwargs)
49
50    def patch(self, request, *args, **kwargs):
51        return self.partial_update(request, *args, **kwargs)
52
53
54class ListCreateAPIView(mixins.ListModelMixin,
55                        mixins.CreateModelMixin,
56                        GenericAPIView)
:

57    """
58    Concrete view for listing a queryset or creating a model instance.
59    """

60    def get(self, request, *args, **kwargs):
61        return self.list(request, *args, **kwargs)
62
63    def post(self, request, *args, **kwargs):
64        return self.create(request, *args, **kwargs)
65
66
67class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
68                            mixins.UpdateModelMixin,
69                            GenericAPIView)
:

70    """
71    Concrete view for retrieving, updating a model instance.
72    """

73    def get(self, request, *args, **kwargs):
74        return self.retrieve(request, *args, **kwargs)
75
76    def put(self, request, *args, **kwargs):
77        return self.update(request, *args, **kwargs)
78
79    def patch(self, request, *args, **kwargs):
80        return self.partial_update(request, *args, **kwargs)
81
82
83class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
84                             mixins.DestroyModelMixin,
85                             GenericAPIView)
:

86    """
87    Concrete view for retrieving or deleting a model instance.
88    """

89    def get(self, request, *args, **kwargs):
90        return self.retrieve(request, *args, **kwargs)
91
92    def delete(self, request, *args, **kwargs):
93        return self.destroy(request, *args, **kwargs)
94
95
96class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
97                                   mixins.UpdateModelMixin,
98                                   mixins.DestroyModelMixin,
99                                   GenericAPIView)
:

100    """
101    Concrete view for retrieving, updating or deleting a model instance.
102    """

103    def get(self, request, *args, **kwargs):
104        return self.retrieve(request, *args, **kwargs)
105
106    def put(self, request, *args, **kwargs):
107        return self.update(request, *args, **kwargs)
108
109    def patch(self, request, *args, **kwargs):
110        return self.partial_update(request, *args, **kwargs)
111
112    def delete(self, request, *args, **kwargs):
113        return self.destroy(request, *args, **kwargs)

5个视图扩展类

 1from rest_framework import status
2from rest_framework.response import Response
3from rest_framework.settings import api_settings
4
5# 新增数据
6class CreateModelMixin:
7    """
8    Create a model instance.
9    """

10    def create(self, request, *args, **kwargs):
11        serializer = self.get_serializer(data=request.data)
12        serializer.is_valid(raise_exception=True)  # 判断
13        self.perform_create(serializer)  # serializer.save()保存数据
14        headers = self.get_success_headers(serializer.data)  
15        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
16
17    # 可以通过重写perform_create方法,在数据保存之前做限制
18    def perform_create(self, serializer):
19        serializer.save()
20
21    def get_success_headers(self, data):
22        try:
23            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
24        except (TypeError, KeyError):
25            return {}
26
27# 查看所有
28class ListModelMixin:
29    """
30    List a queryset.
31    """

32    def list(self, request, *args, **kwargs):
33        queryset = self.filter_queryset(self.get_queryset())
34
35        page = self.paginate_queryset(queryset)
36        if page is not None:
37            serializer = self.get_serializer(page, many=True)
38            return self.get_paginated_response(serializer.data)
39
40        serializer = self.get_serializer(queryset, many=True)
41        return Response(serializer.data)
42
43# 查看单个
44class RetrieveModelMixin:
45    """
46    Retrieve a model instance.
47    """

48    def retrieve(self, request, *args, **kwargs):
49        instance = self.get_object()
50        serializer = self.get_serializer(instance)
51        return Response(serializer.data)
52
53# 更新
54class UpdateModelMixin:
55    """
56    Update a model instance.
57    """

58    def update(self, request, *args, **kwargs):
59        partial = kwargs.pop('partial'False)
60        instance = self.get_object()
61        serializer = self.get_serializer(instance, data=request.data, partial=partial)
62        serializer.is_valid(raise_exception=True)
63        self.perform_update(serializer)
64
65        if getattr(instance, '_prefetched_objects_cache'None):
66            # If 'prefetch_related' has been applied to a queryset, we need to
67            # forcibly invalidate the prefetch cache on the instance.
68            instance._prefetched_objects_cache = {}
69
70        return Response(serializer.data)
71
72    def perform_update(self, serializer):
73        serializer.save()
74
75    def partial_update(self, request, *args, **kwargs):
76        kwargs['partial'] = True
77        return self.update(request, *args, **kwargs)
78
79# 删除
80class DestroyModelMixin:
81    """
82    Destroy a model instance.
83    """

84    def destroy(self, request, *args, **kwargs):
85        instance = self.get_object()
86        self.perform_destroy(instance)
87        return Response(status=status.HTTP_204_NO_CONTENT)
88
89    def perform_destroy(self, instance):
90        instance.delete()

GenericAPIView

  1from django.core.exceptions import ValidationError
2from django.db.models.query import QuerySet
3from django.http import Http404
4from django.shortcuts import get_object_or_404 as _get_object_or_404
5
6from rest_framework import mixins, views
7from rest_framework.settings import api_settings
8
9
10class GenericAPIView(views.APIView):
11    """
12    Base class for all other generic views.
13    """

14    # You'll need to either set these attributes,
15    # or override `get_queryset()`/`get_serializer_class()`.
16    # If you are overriding a view method, it is important that you call
17    # `get_queryset()` instead of accessing the `queryset` property directly,
18    # as `queryset` will get evaluated only once, and those results are cached
19    # for all subsequent requests.
20    queryset = None
21    serializer_class = None
22
23    # If you want to use object lookups other than pk, set 'lookup_field'.
24    # For more complex lookup requirements override `get_object()`.
25    lookup_field = 'pk'
26    lookup_url_kwarg = None
27
28    # The filter backend classes to use for queryset filtering
29    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
30
31    # The style to use for queryset pagination.
32    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
33
34    def get_queryset(self):
35        """
36        Get the list of items for this view.
37        This must be an iterable, and may be a queryset.
38        Defaults to using `self.queryset`.
39
40        This method should always be used rather than accessing `self.queryset`
41        directly, as `self.queryset` gets evaluated only once, and those results
42        are cached for all subsequent requests.
43
44        You may want to override this if you need to provide different
45        querysets depending on the incoming request.
46
47        (Eg. return a list of items that is specific to the user)
48        """

49        assert self.queryset is not None, (
50            "'%s' should either include a `queryset` attribute, "
51            "or override the `get_queryset()` method."
52            % self.__class__.__name__
53        )
54
55        queryset = self.queryset
56        if isinstance(queryset, QuerySet):
57            # Ensure queryset is re-evaluated on each request.
58            queryset = queryset.all()
59        return queryset
60
61    def get_object(self):
62        """
63        Returns the object the view is displaying.
64
65        You may want to override this if you need to provide non-standard
66        queryset lookups.  Eg if objects are referenced using multiple
67        keyword arguments in the url conf.
68        """

69        queryset = self.filter_queryset(self.get_queryset())
70
71        # Perform the lookup filtering.
72        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
73
74        assert lookup_url_kwarg in self.kwargs, (
75            'Expected view %s to be called with a URL keyword argument '
76            'named "%s". Fix your URL conf, or set the `.lookup_field` '
77            'attribute on the view correctly.' %
78            (self.__class__.__name__, lookup_url_kwarg)
79        )
80
81        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
82        obj = get_object_or_404(queryset, **filter_kwargs)
83
84        # May raise a permission denied
85        self.check_object_permissions(self.request, obj)
86
87        return obj
88
89    def get_serializer(self, *args, **kwargs):
90        """
91        Return the serializer instance that should be used for validating and
92        deserializing input, and for serializing output.
93        """

94        serializer_class = self.get_serializer_class()
95        kwargs.setdefault('context', self.get_serializer_context())
96        return serializer_class(*args, **kwargs)
97
98    def get_serializer_class(self):
99        """
100        Return the class to use for the serializer.
101        Defaults to using `self.serializer_class`.
102
103        You may want to override this if you need to provide different
104        serializations depending on the incoming request.
105
106        (Eg. admins get full serialization, others get basic serialization)
107        """

108        assert self.serializer_class is not None, (
109            "'%s' should either include a `serializer_class` attribute, "
110            "or override the `get_serializer_class()` method."
111            % self.__class__.__name__
112        )
113
114        return self.serializer_class
115
116    def get_serializer_context(self):
117        """
118        Extra context provided to the serializer class.
119        """

120        return {
121            'request': self.request,
122            'format': self.format_kwarg,
123            'view': self
124        }
125
126    def filter_queryset(self, queryset):
127        """
128        Given a queryset, filter it with whichever filter backend is in use.
129
130        You are unlikely to want to override this method, although you may need
131        to call it either from a list view, or from a custom `get_object`
132        method if you want to apply the configured filtering backend to the
133        default queryset.
134        """

135        for backend in list(self.filter_backends):
136            queryset = backend().filter_queryset(self.request, queryset, self)
137        return queryset

封装

 1# 第一层封装继承APIView
2
3# 第二层封装继承GenericAPIView
4有两个参数:query=models.Book.object.all()
5          serializers_class=BookSerializers
6三个方法:
7get_serializers()  # 返回的是self.serializers_class
8get_query()        # self.query(查看所有数据)
9get_object()    # 查看单条数据
10
11# 这么写目的是为了提高可扩展性
12from generics import GenericAPIView
13
14class PublishSerializer(GenericAPIView):
15    queryset = models.Publish.objects.all()
16    serializer_class = MySerializer
17    def get(self, request):
18        publish_list = self.get_queryset()  
19        res = self.get_serializer(instance=publish_list, many=True)
20        return Response(data=res.data)
21
22# 第三层封装:继承GenericAPIView, ListModelMixin
23from rest_framework.mixins import UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,ListModelMixin,CreateModelMixin
24
25class PublishSerializer(GenericAPIView, ListModelMixin):
26    queryset = models.Publish.objects.all()
27    serializer_class = MySerializer    
28    def get(self, request):
29        return self.list(request)
30
31# 第四层封装:继承CreateAPIView(以CreateAPIView为例)
32两个get请求时分开的,需要写两个类
33
34from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView, UpdateAPIView, DestroyAPIView,RetrieveAPIView,RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
35
36# 新增功能
37class PublishSerializer(CreateAPIView):
38    queryset = models.Publish.objects.all()
39    serializer_class = MySerializer
40
41# 第五层封装:视图集
42from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet, ViewSet, ViewSetMixin, GenericViewSet
43'''
44ModelViewSet继承了GenericAPIView和所有的Mixin方法(UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,ListModelMixin,CreateModelMixin),所以,只要继承了ModelViewSet,就相当于写了5个接口
45ViewSetMixin:魔法方法,只要继承了它,路由as_view({字典}),必须写在最左侧
46ViewSet继承了ViewSetMixin和APIView
47GenericViewSet继承了ViewSetMixin和GenericAPIView
48'''

49# 5个接口都有了,但是5个接口中有两个get(两个get请求写在一个类中)
50 class PublishView(ModelViewSet):
51     queryset = Publish.objects.all()
52     serializer_class = PublishSerializer
53
54 class PublishView(ReadOnlyModelViewSet):  # 只读   (获取所有和单条   不能新增,不能删除,修改)
55     queryset = Publish.objects.all()
56     serializer_class = PublishSerializer
57
58'''
59一个类里写5个接口,有2个get请求,如何书写路由
60'''

路由组件

 1# 只要是继承ViewSetMixin的视图类,路由写法都变了:as_view({字典})
2ViewSetMixin重写了as_view方法,并且ViewSetMixin必须写在继承关系的最左侧,会按照从左到右的方式查找as_view方法
3# 重点;以后视图类中可以写任意的方法,只需要继承ViewSetMixin后,使用路由做映射即可
4
5
6# 路由使用的第一种方式:
7path('publish/', views.PublishView.as_view(actions={'get''list','post':'create'}))
8#  actions参数,get请求时是list方法,post请求时是create方法
9
10# 第二种方式:自动生成路由
11      在urls.py中
12    1、第一步导入路由的类
13    from rest_framework.routers import SimpleRouter,DefaultRouter
14    '''
15    SimpleRouter,DefaultRouter区别,DefaultRouter会多创建一个根路由,显示所有的路由信息,但是有时会出现问题,    建议使用SimpleRouter
16    '''

17    2、第二步:类实例化得到对象(不用传参数)
18    router=SimpleRouter()
19    3、第三步:注册视图类,
20    router.register('publish',views.PublishView,'publish')  
21    # 前面的publish是路径,后面的publish是别名,用作反向解析的
22
23    # router.register('book',views.BookView)
24
25    4、第四步:加入到总路由中(两种方式)
26
27        urlpatterns = [
28            # 第四步:加入到总路由中方式二
29            path('api/v1/', include(router.urls)),  # api/v1/路由前缀,可以为空
30        ]
31        # 第四步:加入到总路由中:方式一
32        urlpatterns+=router.urls  
33        # 列表的拼接(router.urls是一个列表),会得到一个新的列表包含所有元素(不会去重)
34
35
36
37###action装饰器的作用:给视图函数中自定义的方法做路径的映射
38from rest_framework.decorate import action
39class Login(ViewSet):
40    @action(methods=['GET','POST'],detail=False)  # detail没有pk值为faluse,有pk值为true
41    def login(self,request):
42        return Response('ok')
43
44
45###总结:
46    -第一种:path('publish/', views.PublishView.as_view(actions={'get''list','post':'create'}))
47    -第二种:自动生成 (SimpleRouter,DefaultRouter)
48    -action有什么用
49    -5个方法:create,list,destory。。,不需要使用action映射
50        -如果继承的是 ViewSetMixin, views.APIView +5个视图扩展类之一或者9个视图子类,这种不需要使用action装饰器
posted @ 2022-01-04 11:32  一叶松  阅读(51)  评论(0编辑  收藏  举报