Django(55)GenericAPIView源码分析

Django(55)GenericAPIView源码分析源码分析GenericAPIView继承自APIView,也就是在APIView基础上再做了一层封装,源码如下:classGenericAPIView(views.APIView):query

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

源码分析

GenericAPIView继承自APIView,也就是在APIView基础上再做了一层封装,源码如下:

class GenericAPIView(views.APIView):
    queryset = None
    serializer_class = None

    lookup_field = 'pk'
    lookup_url_kwarg = None

    filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

    pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

    def get_queryset(self):
        assert self.queryset is not None, (
            "'%s' should either include a `queryset` attribute, "
            "or override the `get_queryset()` method."
            % self.__class__.__name__
        )

        queryset = self.queryset
        if isinstance(queryset, QuerySet):
            queryset = queryset.all()
        return queryset

    def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())

        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

        assert lookup_url_kwarg in self.kwargs, (
            'Expected view %s to be called with a URL keyword argument '
            'named "%s". Fix your URL conf, or set the `.lookup_field` '
            'attribute on the view correctly.' %
            (self.__class__.__name__, lookup_url_kwarg)
        )

        filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
        obj = get_object_or_404(queryset, **filter_kwargs)

        self.check_object_permissions(self.request, obj)

        return obj

    def get_serializer(self, *args, **kwargs):
        serializer_class = self.get_serializer_class()
        kwargs.setdefault('context', self.get_serializer_context())
        return serializer_class(*args, **kwargs)

    def get_serializer_class(self):
        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

    def get_serializer_context(self):
        return {
            'request': self.request,
            'format': self.format_kwarg,
            'view': self
        }

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

    @property
    def paginator(self):
        if not hasattr(self, '_paginator'):
            if self.pagination_class is None:
                self._paginator = None
            else:
                self._paginator = self.pagination_class()
        return self._paginator

    def paginate_queryset(self, queryset):
        if self.paginator is None:
            return None
        return self.paginator.paginate_queryset(queryset, self.request, view=self)

    def get_paginated_response(self, data):
        assert self.paginator is not None
        return self.paginator.get_paginated_response(data)

我们可以看到GenericAPIView中定义了6个类属性和8个方法,接下来一个个分析
 

类属性

  • queryset = None
  • serializer_class = None
  • lookup_field = ‘pk’
  • lookup_url_kwarg = None
  • filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
  • pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
     

queryset

  queryset是用来控制视图返回给前端的数据。如果没什么逻辑,可以直接写在视图的类属性中,如果逻辑比较复杂,也可以重写get_queryset方法用来返回一个queryset对象。如果重写了get_queryset,那么以后获取queryset的时候就需要通过调用get_queryset方法。因为queryset 这个属性只会调用一次,以后所有的请求都是使用他的缓存。
 

serializer_class

  serializer_class用来验证和序列化数据的。也是可以通过直接设置这个属性,也可以通过重写get_serializer_class来实现。
 

lookup_field

在检索的时候,根据什么参数进行检索。默认是pk,也就是主键。
 

lookup_url_kwarg

在检索的url中的参数名称。默认没有设置,跟lookup_field保持一致。
 

filter_backends

用于过滤查询集的过滤器后端类的列表。默认值与DEFAULT_FILTER_BACKENDS 设置的值相同。
 

pagination_class

当分页列出结果时应使用的分页类。默认值与 DEFAULT_PAGINATION_CLASS 设置的值相同,即 'rest_framework.pagination.PageNumberPagination'
 

方法

  • get_queryset
  • get_object
  • get_serializer
  • get_serializer_class
  • get_serializer_context
  • filter_queryset
     

get_queryset

def get_queryset(self):
    # 断言queryset是否不为None
    assert self.queryset is not None, (
        "'%s' should either include a `queryset` attribute, "
        "or override the `get_queryset()` method."
        % self.__class__.__name__
    )
    
    # 定义queryset属性,获取父类的queryset,如果父类没有定义类属性`queryset`,那么默认值就是None,就会报上面断言的错误 
    queryset = self.queryset
    # 如果queryset是QuerySet对象,那么返回全部内容
    if isinstance(queryset, QuerySet):
        queryset = queryset.all()
    # 如果不是queryset,那么直接返回
    return queryset

get_queryset默认是返回数据库全部数据,如果想返回其他数据,需要自定义
 

get_object

def get_object(self):
    queryset = self.filter_queryset(self.get_queryset())
    
    # 查找过滤的条件,默认是pk
    lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

    assert lookup_url_kwarg in self.kwargs, (
        'Expected view %s to be called with a URL keyword argument '
        'named "%s". Fix your URL conf, or set the `.lookup_field` '
        'attribute on the view correctly.' %
        (self.__class__.__name__, lookup_url_kwarg)
    )
    
    filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
    obj = get_object_or_404(queryset, **filter_kwargs)
    
    # 可能会引发权限被拒绝
    self.check_object_permissions(self.request, obj)

    return obj

该方法是用于在数据检索(通过pk查找)的时候,返回一条数据的。
 

get_serializer

def get_serializer(self, *args, **kwargs):
    serializer_class = self.get_serializer_class()
    kwargs.setdefault('context', self.get_serializer_context())
    return serializer_class(*args, **kwargs)

返回应该用于验证和反序列化输入以及序列化输出的序列化器实例
 

get_serializer_class

def get_serializer_class(self):
    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

返回用于序列化的类。默认使用self.serializer_class。如果您需要根据传入请求提供不同的序列化,您可能需要重写它。
 

get_serializer_context

def get_serializer_context(self):
    return {
        'request': self.request,
        'format': self.format_kwarg,
        'view': self
    }

提供给序列化的额外上下文。
 

filter_queryset

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

给定一个查询集,使用正在使用的过滤器对其进行过滤。您不太可能想要覆盖此方法,但如果您想将配置的过滤后端应用到默认查询集,您可能需要从列表视图或自定义get_object 方法中调用它。
 

实战案例

class StudentsGenericView(GenericAPIView):
    queryset = Student.objects.all()  # 定义了类属性queryset,告诉视图要针对哪个模型做处理
    serializer_class = StudentModelSerializer  # 定义类属性serlializer_class,告诉视图你的序列化的类是什么
    def get(self, request, *args, **kwargs):
        pk = kwargs.get("pk")
        if pk:
            many = False
            query = self.get_object()  # 通过pk检索数据,返回一条数据
        else:
            many = True
            query = self.get_queryset()  # 返回动态的数据集,默认返回全部
        serializer = self.get_serializer(query, many=many)  # 如果数据对象是queryset对象,many需要为True
        return APIResponse(results=serializer.data)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/165768.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 关于ie下阻止ActiveX控件

    关于ie下阻止ActiveX控件
    最近,公司的项目上有个部分要用到ActiveX控件。可是在访问的时候,就会弹出”Internetexplorer已经阻止站点用不安全方式使用ActiveX控件”一句。查了好多资料,除了更改ie的安全设置,没有其他方法。
    更改ie安全设置,需要更改的几个地方:
    首先,Internet选项–>安全
    1.选中Internet –“自定义级别”– “ActiveX控件和插件 “–“对未标记为可安全执行脚本的ActiveX控件初始化并执行脚本”(启用

  • loadrunner11如何使用java Vuser运行java代码及设置环境变量和上传jdk

    loadrunner11如何使用java Vuser运行java代码及设置环境变量和上传jdk

  • 股票实盘交易接口API(招商证券交易接口api)

    股票配资系统实盘交易接口怎么做有没有好用的实盘交易接口股票实盘交易接口做股票配资系统难免会用到交易接口,好用的能用的接口也少。券商那边也不提供,那索性自己开发股票配资实盘交易接口了。经过多次尝试,总算搞出来了,实时交易接口可以获取用户数据,实时对接,账户信息,委托买入卖出,支持多家券商。我们做股票配资系统的时候遇到过很多次交易接口问题,然后后面终于是解决了,现在我们的股票配资系统已经很完善…

  • DOM「建议收藏」

    DOM「建议收藏」一、DOM简介D——document,没有文档,也就是没有网页,DOM就无从谈起。当创建了一个网页并把它加载到web浏览器中时,DOM就悄然而生。浏览器根据网页文档创建一个文档对象。O——obj

  • SPSS单因素方差分析教程「建议收藏」

    SPSS单因素方差分析教程「建议收藏」SPSS单因素方差分析,非正态分布的秩和检验

  • 港股交易api(如何查看港股)

    港股历史行情数据API接口所有港股历史交易行情数据,完整历史交易/任意时间段查询。1.产品功能支持所有历史港股交易查询;支持指定任意时间段查询;超高的查询效率,秒级返回;所有的交易数据为未复权的数据;全接口支持HTTPS(TLSv1.0/v1.1/v1.2/v1.3);全面兼容AppleATS;全国多节点CDN部署;接口极速响应,多台服务器构建API接口负载均衡。2.API文档API详情地址:https://www.gugudata

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号