3

Consider the following case:

class MyModelManager(models.Manager):
    def my_filter(self):
     return [some code here].filter(field_A__gt=3)

class MyModel(models.Model):
    # some fields
    objects = MyModelManager()


# The way I'd like to use it:
qs = MyModel.objects.filter(field_B__lt=1)
# some code
qs = qs.my_filter()

Notice that I'd like to use the custom my_filter() function on the already filtered queryset. What code should I place in the [some code here] above? Is the structure as a whole correct?

4

3 回答 3

2

我想没有办法做到这一点。MyModel.objects.filter(field_B__lt=1) 将返回 QuerySet 对象,而不是 MyModelManager。您可以像 Ignacio Vazquez-Abrams 提到的那样将它传递给 my_filter 方法,或者首先将 my_filter 应用到您的经理,这将返回 QuerySet 对象,您可以进一步过滤

于 2011-04-28T09:14:56.040 回答
1

您的方法是错误的,因为您只能在从数据库中检索数据时使用 Model.Manager,因此使用两个管理器或尝试在查询集上使用管理器会导致错误。

data = SomeModel.objects.my_manager.all()

或者

data = SomeModel.objects.all()
data = data.my_manager.filter(...)

是错误的,因为你不能使用两个经理......

一种可能的哇是定义一个函数,该函数将查询集作为参数并返回过滤的查询集......

def extra_filter(queryset):
    queryset = queryset.filter(...)

但我不确定这是否有帮助。

最好的方法是定义另一个模型管理器并在需要时将其用于对象...

class SomeManager(models.Manager):
    def get_query_set(self):
        return super(SomeManager, self).get_query_set().filter(<filteer criteria>)

class MyModel(models.Model):
    # some fields
    objects = models.Manager()
    mymanager = SomeManager()

data = MyModel.mymanager.all() 

并且只使用一个...

更新:在 django 中,查询集是惰性的。这意味着,您可以根据需要应用任意数量的过滤器,除非您尝试从过滤器中获取特定记录或尝试对其进行切片,否则不会从数据库中检索数据...文档在这里

所以,两者没有区别

qs = MyModel.objects.filter(field_B__lt=1)
qs = qs.filter(field_A__gt=3)

qs = MyModel.objects.filter(field_A__gt=3)
qs = qs.filter(field_B__lt=1)

所以定义一个管理器来应用特定的过滤是使用管理器的主要原因......

你定义你的经理:

class SomeManager(models.Manager):
    def get_query_set(self):
        return super(SomeManager, self).get_query_set().filter(field_A__gt=3)

然后你用其他过滤条件调用它:

Somemodel.mymodelmanager.filter(field_B__lt=1, ....)

django 将添加所有过滤器并在您想要时评估查询。

所以如果是你经常使用的过滤器,manager我是最好的选择...

例如,我在大多数数据库模型中都有有效的 _ 字段和过滤无效条目的val管理器。因此,当我希望过滤所有有效数据(90% 的时间)时,我使用

Somemodel.val.filter(...)

在我需要所有数据的情况下,我只使用基本的 django 管理器:

Somemodel.objects.filter(...)
于 2011-04-28T11:56:03.183 回答
0
class MyModelManager(models.Manager):
    def my_filter(self, qs=None):
        if qs is None:
            qs = [however you got it before]
        return qs.filter(field_A__gt=3)

然后只需将您的查询集传递给它。

于 2011-04-28T09:11:20.553 回答