Django Rest Framework 视图APIViews

 

APIView View区别

- APIView继承的View;

 1 """
 2 部分源码
 3 """
 4 def as_view(cls, **initkwargs):
 5     if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
 6         def force_evaluation():
 7             raise RuntimeError(
 8                 'Do not evaluate the `.queryset` attribute directly, '
 9                 'as the result will be cached and reused between requests. '
10                 'Use `.all()` or call `.get_queryset()` instead.'
11             )
12         cls.queryset._fetch_all = force_evaluation
13 
14     view = super(APIView, cls).as_view(**initkwargs)
15     view.cls = cls
16     view.initkwargs = initkwargs
17 
18     # Note: session based authentication is explicitly CSRF validated,
19     # all other authentication is CSRF exempt.
20     return csrf_exempt(view)

- 14 行代码中执行父类的 as_view(); 在父类的 as_view() 方法中最后调用了 self.dispatch(); 实际执行的是 APIView中的 dispatch() 方法;

 1 """
 2 View源码
 3 """
 4     def as_view(cls, **initkwargs):
 5         for key in initkwargs:
 6             if key in cls.http_method_names:
 7                 raise TypeError("You tried to pass in the %s method name as a "
 8                                 "keyword argument to %s(). Don't do that."
 9                                 % (key, cls.__name__))
10             if not hasattr(cls, key):
11                 raise TypeError("%s() received an invalid keyword %r. as_view "
12                                 "only accepts arguments that are already "
13                                 "attributes of the class." % (cls.__name__, key))
14 
15         def view(request, *args, **kwargs):
16             self = cls(**initkwargs)
17             if hasattr(self, 'get') and not hasattr(self, 'head'):
18                 self.head = self.get
19             self.request = request
20             self.args = args
21             self.kwargs = kwargs
22             return self.dispatch(request, *args, **kwargs)
23         view.view_class = cls
24         view.view_initkwargs = initkwargs
25 
26         # take name and docstring from class
27         update_wrapper(view, cls, updated=())
28 
29         # and possible attributes set by decorators
30         # like csrf_exempt from dispatch
31         update_wrapper(view, cls.dispatch, assigned=())
32         return view

 

  - APIView中的 dispatch:

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

  

  - 在这里重新封装了 request对象

    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        assert isinstance(request, HttpRequest), (
            'The `request` argument must be an instance of '
            '`django.http.HttpRequest`, not `{}.{}`.'
            .format(request.__class__.__module__, request.__class__.__name__)
        )

        self._request = request
        self.parsers = parsers or ()
        self.authenticators = authenticators or ()
        self.negotiator = negotiator or self._default_negotiator()
        self.parser_context = parser_context
        self._data = Empty
        self._files = Empty
        self._full_data = Empty
        self._content_type = Empty
        self._stream = Empty

        if self.parser_context is None:
            self.parser_context = {}
        self.parser_context['request'] = self
        self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET

        force_user = getattr(request, '_force_auth_user', None)
        force_token = getattr(request, '_force_auth_token', None)
        if force_user is not None or force_token is not None:
            forced_auth = ForcedAuthentication(force_user, force_token)
            self.authenticators = (forced_auth,)

 

 

封装ModelViewSet

- 将 queryset,serializer_class 单独摘出来;用一个类去获取

class GenericAPIView(ViewSetMixin, APIView):
    """
    用来获取 query_set 和 序列器中的 类
    """

    def get_queryset(self):
        return self.queryset.all()

    def get_serializer(self, *args, **kwargs):
        return self.serializer(*args, **kwargs)

class TeamView(GenericAPIView):
    queryset = models.Team.objects.all()
    serializer_class = serializers.TeamSerializer

 

- 将每一个请求单独摘出来,封装成类:

class ListModelMixin:
    def list(self):
        team_obj = self.get_query_set()
        ser_obj = self.get_serializer(team_obj, many=True)
        return Response(ser_obj.data)


class CreateModelMixin:
    def create(self, request):
        ser_obj = serializers.TeamSerializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        return Response(ser_obj.errors)


class TeamView(GenericAPIView,ListModelMixin, CreateModelMixin):
    queryset = models.Team.objects.all()
    serializer_class = serializers.TeamSerializer
    
    def get(self, request):
        return self.list()

    def post(self, request):
        return self.create(request)

 

- 图解:

 

posted @ 2018-10-30 18:41  浮生凉年  阅读(405)  评论(0编辑  收藏  举报