Django查询集包含过滤器,但“反之亦然”

anauzrmj  于 2023-07-01  发布在  Go
关注(0)|答案(1)|浏览(161)

我有一个模型:

class Sources(models.Model):
    ...
    vendor = models.CharField(max_value=128, blank=True, null=True)
    ...

例如一些数据:

select id, vendor from "webgui_sources";
 id |       vendor
----+-----------------
  6 | oracle
  5 | microsoft

然后我有一个字符串像“oracle; microsoft;apache”,我需要检查是否有模型将vendor值包含在此字符串中。因此,基本上我需要收集所有供应商的vendor值包含到“oracle; microsoft;apache”。
鉴于

Sources.objects.filter(vendor__icontains='oracle;microsoft;apache')

生成以下SQL查询:

SELECT * FROM "webgui_sources" WHERE UPPER("webgui_sources".vendor) LIKE UPPER('oracle;microsoft;apache')

我需要交换字段并得到如下内容:

SELECT * FROM "webgui_sources" WHERE UPPER('oracle;microsoft;apache') LIKE UPPER("webgui_sources".vendor)

我尝试使用extra,它完成了这项工作,但由于不建议使用extra,因此我尝试创建自定义查找:

class IContainsReverse(PatternLookup):
    
     lookup_name = "icontains_reverse"

    

     def as_sql(self, compiler, connection):
        
          lhs_sql, params = self.process_lhs(compiler, connection)
        
          params.extend([self.rhs])
        
          return "%s ~* {}".format(lhs_sql), params


 

Field.register_lookup(IContainsReverse)

这个lookup允许我生成这样的查询:

Sources.objects.filter(vendor__icontains_reverse='oracle;microsoft;apache')
select * from "webgui_sources" where 'oracle;microsoft;apache' ~* "webgui_sources".vendor;

它或多或少可以工作,但看起来很笨重,只能与PostgreSQL一起工作。我希望有一个更Django方式的解决方案来做到这一点,有人能建议更多的Django方式的替代方案吗?先谢谢你。

xqnpmsa8

xqnpmsa81#

你可以用**.alias(…)[Django-doc]为表达式注入值,然后在该别名上注入.filter(…)**[Django-doc]:

from django.db.models import F, Value

Sources.objects.alias(filter_value=Value('oracle;microsoft;apache')).filter(
    filter_value_icontains=F('vendor')
)

也就是说,您可以使用以下命令进行查询:

from django.db.models import Q

vals = 'oracle;microsoft;apache'
Sources.objects.filter(
    *[Q(vendor__iexact=v) for v in vals.split(';')], _connector=Q.OR
)

相关问题