基于django 开发的框架 jumpserver 源码解析(四)对基于视图的 几大视图类 跟 rest_framework 的 序列化过程

 对基于视图的 几大视图类  跟   rest_framework 的 序列化过程

django 的 视图类 分为两大派系。

第一种是 django 自带的templateview 。

templateview 源码

class TemplateView(TemplateResponseMixin, ContextMixin, View):
    """
    Render a template. Pass keyword arguments from the URLconf to the context.
    """
    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

templateview 自己实现了 get 方法 而 它的  get_context_data  方法  跟 render_to_response 方法都是继承自父类。render_to_response 是继承TemplateResponseMixin 类,get_context_data 是继承ContextMixin 。源码就不贴出来了,很简单。

第二种 是  是   rest_framework_bulk  的ViewSet  类。BulkModelViewSet 所有的方法 create , list, 等等方法继承自父类,举个列子 而 list 方法中 用到的   get_queryset   filter_queryset   get_serializer 也是 继承自父类 ,需要时进行重写。

class BulkModelViewSet(bulk_mixins.BulkCreateModelMixin,
                       bulk_mixins.BulkUpdateModelMixin,
                       bulk_mixins.BulkDestroyModelMixin,
                       ModelViewSet):

下面分析 rest_framework 的 序列化 过程

如果 django rest_framework 需要对数据进行序列化操作,这是 restifulj 接口的 一部分,在 viewset 类 调用 list ,crate,等方法的之后 会 对 model orm 查询产生的 结果集 ,ListModelMixin 为例以 下面看 源代码。 

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

这个会调用 get_serializer 方法  对 对象 进行序列化操作,按照 python 继承规则 ,查找 get_serializer 方法, 源码 如下,

   def get_serializer(self, *args, **kwargs):
        """
        Return the serializer instance that should be used for validating and
        deserializing input, and for serializing output.
        """
        serializer_class = self.get_serializer_class()
        kwargs['context'] = self.get_serializer_context()
        return serializer_class(*args, **kwargs)

    def get_serializer_class(self):
        """
        Return the class to use for the serializer.
        Defaults to using `self.serializer_class`.

        You may want to override this if you need to provide different
        serializations depending on the incoming request.

        (Eg. admins get full serialization, others get basic serialization)
        """
        assert self.serializer_class is not None, (
            "'%s' should either include a `serializer_class` attribute, "
            "or override the `get_serializer_class()` method."
            % self.__class__.__name__
        )

        return self.serializer_class

对 viewset 类   有没有 serializer_class 做了一个 判断。没有 serializer_class 断言报错。如有有 就 把 data 传进serializer_class 的__init__方法。返回list 方法 返回 response 对象的 时候,这个数据集 作为了 serializer_class 的属性 一起返回去。serializer.data 见源码。

class BaseSerializer(Field):
    """
    The BaseSerializer class provides a minimal class which may be used
    for writing custom serializer implementations.

    Note that we strongly restrict the ordering of operations/properties
    that may be used on the serializer in order to enforce correct usage.

    In particular, if a `data=` argument is passed then:

    .is_valid() - Available.
    .initial_data - Available.
    .validated_data - Only available after calling `is_valid()`
    .errors - Only available after calling `is_valid()`
    .data - Only available after calling `is_valid()`

    If a `data=` argument is not passed then:

    .is_valid() - Not available.
    .initial_data - Not available.
    .validated_data - Not available.
    .errors - Not available.
    .data - Available.
    """

    def __init__(self, instance=None, data=empty, **kwargs):
        self.instance = instance
        if data is not empty:
            self.initial_data = data
        self.partial = kwargs.pop('partial', False)
        self._context = kwargs.pop('context', {})
        kwargs.pop('many', None)
        super(BaseSerializer, self).__init__(**kwargs)

当 结果集 传到 serializer_class  形参 instance  接收了这个参数,然后 BaseSerializer 的 data  属性是什么,贴出源码

  @property
    def data(self):
        if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
            msg = (
                'When a serializer is passed a `data` keyword argument you '
                'must call `.is_valid()` before attempting to access the '
                'serialized `.data` representation.\n'
                'You should either call `.is_valid()` first, '
                'or access `.initial_data` instead.'
            )
            raise AssertionError(msg)

        if not hasattr(self, '_data'):
            if self.instance is not None and not getattr(self, '_errors', None):
                self._data = self.to_representation(self.instance)
            elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
                self._data = self.to_representation(self.validated_data)
            else:
                self._data = self.get_initial()
        return self._data

 

这个data 属性  , 看源码 会 调用 to_representation 方法 对 _instaance 进行除了 ,这个 _instance 属性 保存了 结果集,下面看

to_representation 是什么样的?按照 继承 顺序 查找 to_representations 源码如下

 

def to_representation(self, instance):
        """
        Object instance -> Dict of primitive datatypes.
        """
        ret = OrderedDict()
        fields = self._readable_fields

        for field in fields:
            try:
                attribute = field.get_attribute(instance)
            except SkipField:
                continue

            # We skip `to_representation` for `None` values so that fields do
            # not have to explicitly deal with that case.
            #
            # For related fields with `use_pk_only_optimization` we need to
            # resolve the pk value.
            check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
            if check_for_none is None:
                ret[field.field_name] = None
            else:
                ret[field.field_name] = field.to_representation(attribute)

        return ret

就是  Serializer 根据自己的 filed 取出 queryset 中的相关字段 ,放进一个有序列表里面,作为Serializer 的data 属性。所谓序列化过程就是这个样子,list 方法 >> queset>> 序列化>>  返回前端。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是基于Djangorest_framework框架的ModelViewSet视图解析: 1.基本介绍 ModelViewSet视图Django框架rest_framework模块中的一个视图类,它继承了GenericAPIView和Mixins,提供了对资的CRUD操作。ModelViewSet视图类中提供了一系列的方法,如list、create、retrieve、update、partial_update、destroy等,这些方法对应着HTTP请求中的GET、POST、PUT、PATCH、DELETE等动词。 2.解析 ModelViewSet视图码主要涉及到以下几个部分: (1)视图类的定义 ``` class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): """ A viewset that provides default `create()`, `retrieve()`, `update()`, `partial_update()`, `destroy()` and `list()` actions. """ pass ``` 从码可以看出,ModelViewSet继承了CreateModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin和ListModelMixin这些视图混合类,以及GenericViewSet类。 (2)视图方法的实现 a. list方法 ``` def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset()) page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) ``` list方法用于返回资列表,它首先通过get_queryset方法获取查询集,然后通过filter_queryset方法对查询集进行过滤,最后通过get_serializer方法将查询集序列为JSON数据返回给客户端。 b. create方法 ``` def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) ``` create方法用于创建资,它首先通过get_serializer方法获取序列器,然后通过perform_create方法进行资的创建,最后返回HTTP 201 Created状态码以及资的JSON数据。 c. retrieve方法 ``` def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) return Response(serializer.data) ``` retrieve方法用于获取单个资,它通过get_object方法获取资实例,然后通过get_serializer方法将资实例序列为JSON数据返回给客户端。 d. update方法 ``` def update(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) instance = self.get_object() serializer = self.get_serializer(instance, data=request.data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) return Response(serializer.data) ``` update方法用于更新资,它首先通过get_object方法获取资实例,然后通过get_serializer方法获取序列器,最后通过perform_update方法进行资的更新,最终返回更新后的资JSON数据。 e. partial_update方法 ``` def partial_update(self, request, *args, **kwargs): kwargs['partial'] = True return self.update(request, *args, **kwargs) ``` partial_update方法用于部分更新资,它通过调用update方法,并将partial参数设置为True,进行资的部分更新。 f. destroy方法 ``` def destroy(self, request, *args, **kwargs): instance = self.get_object() self.perform_destroy(instance) return Response(status=status.HTTP_204_NO_CONTENT) ``` destroy方法用于删除资,它首先通过get_object方法获取资实例,然后通过perform_destroy方法进行资的删除,最终返回HTTP 204 No Content状态码。 3.总结 ModelViewSet视图Django框架rest_framework模块中的一个视图类,它继承了GenericAPIView和Mixins,提供了对资的CRUD操作。通过对视图类的解析,我们可以深入了解ModelViewSet视图的内部实现,从而更好地理解和使用该视图类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值