首页 > 解决方案 > Django过滤器替换

问题描述

假设我有以下模型,它有一个方法 variables():

class Example(models.Model):
    text = models.CharField(max_length=255)

    def variants(self):
        return Example.objects.filter(text=remove('xy', self.text))

这个想法是在从文本中删除某些字符后获取文本相同的所有对象。例如,如果 self.text 是 'axxyy',它应该与具有文本 'a' 的对象匹配。函数 remove() 不涉及数据库,它返回一个已删除给定字符的新字符串。这工作正常。

但是,我需要在比较的两侧执行相同的操作,以便 variables() 的行为如下所示:

    def variants(self):
        return Example.objects.filter(remove('xy', text)=remove('xy', self.text))

在这种情况下,如果 self.txt 是 'axxyy',它应该与 'a'、'ax、'axx'、'xayy' 等匹配,但不应与 'aa' 匹配,例如,因为 'a' ! = 'aa' 删除后。再一次,我不想从数据库中删除“xy”,只是为了比较。

我可以用 Python 做到这一点,但我想知道是否有办法在数据库级别做到这一点?我一直在阅读有关 Func() 表达式的文档,例如 Replace,但还没有找到解决方案。

标签: djangopostgresqlfiltering

解决方案


使用 django 的 Replace 函数进行注释,然后对该注释进行过滤。

from django.db.models.functions import Replace
from django.db.models import Value
...

    def variants(self):
        return Example.objects.annotate(
            removed_x=Replace('text', Value('x'), Value('')),
            removed_xy=Replace('removed_x', Value('y'), Value('')),
        ).filter(
            removed_xy=self.text.replace('x' , '').replace('y', '')
        )

请注意,替换参数Value('')是可选的,因为这实际上Replace()是默认值,但在示例中更明确。

随着字符数量的增加,这不能很好地扩展,但是如果您的数据库支持,使用正则表达式可能会有更好的解决方案(Postgres)


推荐阅读