Django-filter:按模型属性过滤

问题描述 投票:1回答:2

我在several places上读到,不可能使用属性过滤Django查询集,因为Django ORM不知道如何将它们转换为SQL。

但是,一旦获取数据并将其加载到内存中,就可以使用这些属性在Python中过滤它们。

我的问题是:是否有任何库允许查询集按内存中的属性进行过滤?如果没有,查询集究竟必须如何被篡改才能实现这一点?以及如何将django-filter纳入其中?

django properties django-queryset django-filter
2个回答
2
投票

你有困难的财产吗?如果没有,您可以将其重写为queryset,如下所示:

from django.db import models

class UserQueryset(models.Manager):

    def get_queryset(self):

        return super().get_queryset().annotate(
            has_profile=models.Exists(Profile.objects.filter(user_id=models.OuterRef('id')))
        )

class User(models.Model):
    objects = UserQueryset


class Profile(models.Model):
    user = models.OneToOneField(User, related_name='profile')


# When you want to filter by has profile just use it like has field has profile

user_with_profiles = User.objects.filter(has_profile=True)

可能不是你想要的,但在某些情况下它可以帮助你


1
投票

django-filter想要并假设您正在使用查询集。一旦你获取一个查询集并将其更改为list,那么下游的任何东西都需要能够处理list或者只是遍历列表,这不再是一个查询集。

如果您有像django_filters.FilterSet

class FooFilterset(django_filters.FilterSet):
    bar = django_filters.Filter('updated', lookup_expr='exact')
    my_property_filter = MyPropertyFilter('property')
    class Meta:
        model = Foo
        fields = ('bar',  'my_property_filter')

然后你可以写MyPropertyFilter像:

class MyPropertyFilter(django_filters.Filter):
    def filter(self, qs, value):
        return [row for row in qs if row.baz == value]

在这一点上,MyProperteyFilter下游的任何东西都会有一个清单。

注意:我相信fields的顺序应该有你的自定义过滤器,MyPropertyFilter最后,因为它将始终在正常的查询集过滤器后处理。


所以,你刚刚打破了“queryset”API,对于某些破碎的值。此时,您将不得不解决下游任何错误。如果FilterSet需要一个.count成员之后的任何东西,你可以改变MyPropertyFilter像:

class MyPropertyFilter(django_filters.Filter):
    def filter(self, qs, value):
        result = [row for row in qs if row.baz == value]
        result.count = len(result)
        return result

你处于未知领域,你将不得不破解你的方式。

无论如何,我之前已经做过这件事并且并不可怕。只要他们来的错误。

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