【问题标题】:Django Custom Manager to dynamically filter archived objectsDjango 自定义管理器动态过滤归档对象
【发布时间】:2021-01-27 16:51:18
【问题描述】:

假设我有一个模型:

class Car(models.Model):
    name = models.CharField(max_length=50)
    is_active = models.BooleanField(default=True)

当我查询 Car 时,我总是希望返回满足 is_active=True 的对象。 为此,在 StackOverFlow 上搜索,我发现我最好的选择是使用 ModelManager,如下所示:

class CarManager(models.ModelManager):
    def get_queryset(self):
        return super().get_queryset().filter(is_active=True)

并且,在我的模型中使用这个 Manager

class Car(models.Model):
    name = models.CharField(max_length=50)
    is_active = models.BooleanField(default=True)
    objects = CarManager()

使用此解决方案始终返回活动的 Car 查询集。 但是,有时我也想返回非活动的 Car 查询集,我不想编写另一个 ModelManager

详细说明,

  1. 当我跑步时,

    汽车.objects.all() 或者,

    Car.objects.filter(name__contains='Car') 或者,

    Car.objects.filter(is_active=True)

我只想要活动的 Car 查询集。

  1. 当我跑步时,

    Car.objects.filter(is_active=False)

我想要非活动的 Car 查询集。

而且,我想使用单个 ModelManager 和默认方法(get、filter、all 等)来实现这一点。为什么我想要这个是因为它已经在很多地方被使用了。

那么,有什么办法可以做到这一点吗?欢迎任何建议或见解。

提前感谢您的帮助。

【问题讨论】:

    标签: python django


    【解决方案1】:

    恐怕不可能,因为您正在覆盖经理的基本查询集。除了创建另一个管理器之外,您可以做的是实现一个额外的方法,该方法返回一个仅包含非活动汽车的查询集,例如:

    class CarManager(models.ModelManager):
        def get_queryset(self):
            return super().get_queryset().filter(is_active=True)
    
        def get_inactive_cars(self):
            return super().get_queryset().filter(is_active=False)
    
    

    然后替换您检索非活动查询集的查询集:

    Car.objects.get_inactive_cars()
    
    

    【讨论】:

    • 哦,不可以使用查询的参数吗?比如,检查是否在过滤器中使用了is_active并返回相应的结果?
    【解决方案2】:

    所以,经过长时间的研究和查阅文档和 Django 源代码,我想出了这个 for filter() 方法:

    class CarManager(models.ModelManager):
        def filter(self, *args, **kwargs):
            if kwargs.get('is_active') == False:
                return super().get_queryset().filter(*args, **kwargs)
            return self.get_queryset().filter(*args, **kwargs)
        
        def get_queryset(self):
            return super().get_queryset().filter(is_active=True)
    

    在这里,我重写了 filter() 方法,所以:

    1. 如果传递了 is_active=False,则调用父级(默认)get_queryset() 后跟 filter()。
    2. 如果未传递 is_active 或传递 is_active=True,则调用覆盖的 get_queryset() 方法(返回活动 Car 查询集),然后调用过滤器() 方法。

    如果有任何其他解决方案或更好的做法,请务必提及。谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-15
      • 1970-01-01
      • 2011-02-05
      • 2013-07-20
      • 2013-01-15
      • 1970-01-01
      • 2018-05-01
      • 2016-07-01
      相关资源
      最近更新 更多