Django,从模型方法进行查询过滤

问题描述 投票:0回答:6

我有这些型号:

def Foo(Models.model):
    size = models.IntegerField()
    # other fields

    def is_active(self):
         if check_condition:
              return True
         else:
              return False

def Bar(Models.model):
     foo = models.ForeignKey("Foo")
     # other fields

现在我想查询具有活动 Foo 的 Bars:

Bar.objects.filter(foo.is_active())

我收到错误,例如

SyntaxError at /
('non-keyword arg after keyword arg'

我怎样才能实现这个目标?

django django-queryset
6个回答
44
投票

您无法查询模型方法或属性。要么在查询中使用其中的条件,要么使用列表理解或genex在Python中进行过滤。


33
投票

您还可以使用自定义管理器。然后你可以运行这样的东西:

Bar.objects.foo_active()

你所要做的就是:

class BarManager(models.Manager):
    def foo_active(self):
       # use your method to filter results
       return you_custom_queryset

查看文档


26
投票

我有类似的问题:我正在使用基于类的视图

object_list
,我必须按模型的方法进行过滤。 (将信息存储在数据库中不是一个选项,因为该属性是基于时间的,我必须创建一个 cronjob 和/或...没办法

我的答案是无效的,我不知道它如何在更大的数据上扩展;但是,它有效:

q = Model.objects.filter(...)...
# here is the trick
q_ids = [o.id for o in q if o.method()]
q = q.filter(id__in=q_ids)

10
投票

您无法过滤方法,但是如果 Foo 上的 is_active 方法检查 Foo 上的属性,您可以使用双下划线语法,如

Bar.objects.filter(foo__is_active_attribute=True)


0
投票

显然,正如 Ignacio Vazquez-Abrams 指出的那样,您无法在视图中查询模型方法。相反,我会在视图中应用所需的过滤器逻辑。

例如,当

check_condition
是日期范围时:

class BarView(ListView):
    model = Bar
    template_name = "app/bar.html"

    def get_queryset(self):
        # Filter for a condition (here the condition is a date range)
        now = timezone.now().date()
        return Bar.objects.filter(foo__start_date__lte=now, foo__end_date__gte=now)

0
投票

一种选择是使用 django-denorm 本质上动态创建模型字段:

@denorm.denormalized(models.BooleanField, null=True, default=False)
@denorm.depend_on_related("Bar")
def is_active(self):
    # return something

然后您可以按

foo__is_active=True
进行过滤。

添加后,使用

manage.py makemigrations
manage.py migrate
manage.py denorm-init
准备数据库。这可能不是最好的解决方案,因为模型应该主要代表数据库结构,本身不做太多工作,但这就是我的前任所做的。

© www.soinside.com 2019 - 2024. All rights reserved.