简体   繁体   English

如果 queryset 和 get_queryset 都定义在从 GenericViewSet 继承的 Django ViewSet 上会发生什么

[英]What happens if queryset and get_queryset are both defined on a Django ViewSet that inherits from GenericViewSet

I've inherited some Django code and I am struggling to work out what the previous developers have intended with their code.我继承了一些 Django 代码,我正在努力弄清楚以前的开发人员对他们的代码的意图。

There is a ViewSet which is configured, which inherits from GenericViewSet.有一个已配置的 ViewSet,它继承自 GenericViewSet。 In the class it defines a queryset variable but also defines a get_queryset method.在该类中,它定义了一个queryset变量,但也定义了一个get_queryset方法。 I'm struggling to work out from the docs and tutorials what this even means?我正在努力从文档和教程中找出这意味着什么? What's more interesting is that the get_queryset method returns a queryset of one type, but the queryset variable defines a different type.更有趣的是get_queryset方法返回一种类型的查询集,但queryset变量定义了不同的类型。

What I'm hoping for is for both querysets to be combined (which is the desired behaviour, and which appears to be happening on one server, but not another, so some additional investigation will be needed to work out why)我希望将两个查询集结合起来(这是所需的行为,并且似乎发生在一台服务器上,而不是另一台服务器上,因此需要进行一些额外的调查来找出原因)

Code below:代码如下:

class FeedbackFieldViewSet(NestedViewSetMixin,
                       customer_mixins.CustomerProviderMixin,
                       mixins.ListModelMixin,
                       viewsets.GenericViewSet):
    ##
    # Instantiates and returns the list of permissions required by this viewset.
    #
    # @return The list of permissions.
    #
    def get_permissions(self):
        # Maps action names to tuples of permission classes.
        permissionDict = {
            "list": self.listPermissionClasses,
        }

        if self.action in permissionDict:
            return [permission() for permission in permissionDict[self.action]]

        if self.request.method == "OPTIONS":
            # Anyone can submit an options request
            return []

        raise ProgrammingException("A request with an unknown permission model was received.")

    listPermissionClasses = (IsFeatureEnabled,)

    ##
    # Overrides the get_queryset method to join the custom feedback fields
    # with the default feedback fields.
    #
    def get_queryset(self):
        queryset = super(FeedbackFieldViewSet, self).get_queryset().filter(
            deleted           = False,
            recordContentType = ContentType.objects.get(
                app_label = "hubpro_api",
                model     = "feedback"))

        return list(chain(queryset, FeedbackField.objects.all()))

    serializer_class = FeedbackFieldSerializer
    feature          = "feedback"
    queryset         = CustomField.objects.all()

There are different usages for get_queryset and self.queryset eg the definition of self.queryset is used to determine the basename of a view in the router's url definition (see Notes on: http://www.django-rest-framework.org/api-guide/routers/#usage ) if you don't provide a queryset as an attribute of the view DRF will raise an error in the router.有不同的用途get_querysetself.queryset例如定义self.queryset用于确定在路由器的网址定义视图的基本名称(见注: http://www.django-rest-framework.org/ api-guide/routers/#usage ) 如果您不提供查询集作为视图 DRF 的属性将在路由器中引发错误。

In your specific case (from what your source snippet shows) there is no use for the queryset , if it is not used anywhere else (cannot say for sure based on this snippet)!在您的特定情况下(根据您的源代码片段显示的内容),如果没有在其他任何地方使用queryset则它没有用处(无法根据此代码片段确定)!

My suggestions for a refactoring to ease the readability and clear things up would be to create a custom method in the queryset for the filter you use in the get_queryset method and I would remove the queryset completely ( if its safe depends on the rest of your code ) because the next coder will need to dig through the code like you did to understand it.我的重构,缓解可读性和清晰的东西的建议是创建在查询集为您在使用过滤器自定义的方法get_queryset方法,我会删除queryset完全(如果它的安全依赖于你的代码的其余部分) 因为下一个编码员将需要像您一样深入了解代码才能理解它。

Coding is about 80% reading 20% coding and always leave the code better than you found it (~ clean code, robert c. martin).编码大约是 80% 阅读 20% 编码,并且总是让代码比你发现的更好(~干净的代码,robert c. martin)。

The gist of what get_queryset method in viewsets is doing is something along the lines of get_queryset方法的要点是

def get_queryset(self):
    return self.queryset

Since you have overridden the get_queryset method and calling super , you're altering the result.由于您已覆盖get_queryset方法并调用super ,因此您正在更改结果。

This probably won't be useful for anyone else, but for completeness I'm answering it.这可能对其他人没有用,但为了完整起见,我正在回答它。

Indeed both the queryset and get_queryset querysets get combined.事实上,无论是querysetget_queryset查询集得到结合。 It looks like the get_queryset call to super(FeedbackFieldViewSet, self).get_queryset() gets the queryset value ( CustomField.objects.all() ) and then the list(chain(queryset, FeedBackField,objects.all())) is what combines the two querysets.看起来get_queryset调用super(FeedbackFieldViewSet, self).get_queryset()获取查询集值( CustomField.objects.all() )然后list(chain(queryset, FeedBackField,objects.all()))是什么结合两个查询集。

My bug was to do with paging, ie the missing values were missing because they weren't on the first page of results.我的错误与分页有关,即缺失值缺失,因为它们不在结果的第一页上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM