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)
- 图解: