Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django过滤器,更换_Django_Postgresql_Filtering - Fatal编程技术网

Django过滤器,更换

Django过滤器,更换,django,postgresql,filtering,Django,Postgresql,Filtering,假设我有以下模型,其中有一个方法variants(): 其思想是在从文本中删除某些字符后,获取文本相同的所有对象。例如,如果self.text为“axxyy”,则它应与包含文本“a”的对象匹配。函数remove()不接触数据库,它返回一个已删除给定字符的新字符串。这个很好用 但是,我需要在比较的两侧执行相同的操作,以便variants()的行为如下所示: def variants(self): return Example.objects.filter(remove('x

假设我有以下模型,其中有一个方法variants():

其思想是在从文本中删除某些字符后,获取文本相同的所有对象。例如,如果self.text为“axxyy”,则它应与包含文本“a”的对象匹配。函数remove()不接触数据库,它返回一个已删除给定字符的新字符串。这个很好用

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

    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,但还没有找到解决方案。

使用django的Replace函数进行注释,然后对该注释进行筛选

从django.db.models.functions导入替换
从django.db.models导入值
...
def变体(自身):
返回Example.objects.annotate(
已删除\u x=替换('text',Value('x'),Value(''),
移除的_xy=替换('removed_x',Value('y'),Value('')),
).过滤器(
已删除_xy=self.text.replace('x','').replace('y','')
)
请注意,替换参数
Value(“”)
是可选的,因为这实际上是
Replace()
的默认值,但在示例中更显式


随着字符数的增加,这种方法不能很好地扩展,但是如果您的DB支持使用django的Replace函数进行注释(Postgres),那么使用regex可能会有更好的解决方案,然后对该注释进行过滤

从django.db.models.functions导入替换
从django.db.models导入值
...
def变体(自身):
返回Example.objects.annotate(
已删除\u x=替换('text',Value('x'),Value(''),
移除的_xy=替换('removed_x',Value('y'),Value('')),
).过滤器(
已删除_xy=self.text.replace('x','').replace('y','')
)
请注意,替换参数
Value(“”)
是可选的,因为这实际上是
Replace()
的默认值,但在示例中更显式


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

我在回答我自己的问题,因为我能够在Tim Nyborg的答案的帮助下实现这一点。我不确定这是否是实现这一点的最漂亮、最有效的方法,但它似乎可以很快地处理我正在处理的数据量,并且可以很好地扩展以适应不断增长的替换模式。此解决方案仅适用于Postgres,因为它使用“regexp_replace”进行替换

以下是示例实现:

def variants(self):
    patterns = [
        ('[xyz️w]', ''),
        ('[\u00A0]', ' '),
        # etc.
    ]

    # Replace characters in self.text
    text_i = self.text
    for old, new in patterns:
        text_i = re.sub(old, new, text_i)

    # Replace the same characters in all other objects
    queryset = Example.objects.all()
    for i, value in enumerate(patterns):
        old, new = value
        queryset = queryset.annotate(
            **{f'text_{i}': Func(F(f'text_{i - 1}' if i > 0 else 'text'),
                                 Value(old), Value(new), Value('g'),
                                 function='regexp_replace')})
    else:
        # Filter all where replaced texts are the same
        queryset = queryset.filter(**{f'text_{i}': text_i}).exclude(pk=self.pk)

    return queryset
Regex本身解决了大多数问题,因为可以一次替换多个字符,但我的模式相当复杂,所以我将它们拆分为列表,并用动态构建的字段名进行注释

话虽如此,如果我真的继续使用这个解决方案,或者更确切地说,在模型中添加一个字段来存储每个对象的“text_I”(替换已完成)值,那么我还不是100%,然后就这样做:

def variants(self):
    return Example.objects.filter(text_i=self.text_i).exclude(pk=self.pk)

我只需要考虑“Tr.Tythi”是否足够稳定,这样我就不必在最初的创作后不断地更新它们。

< P>我回答了我自己的问题,因为我能够在Tim Nyborg的回答的帮助下完成这项工作。我不确定这是否是实现这一点的最漂亮、最有效的方法,但它似乎可以很快地处理我正在处理的数据量,并且可以很好地扩展以适应不断增长的替换模式。此解决方案仅适用于Postgres,因为它使用“regexp_replace”进行替换

以下是示例实现:

def variants(self):
    patterns = [
        ('[xyz️w]', ''),
        ('[\u00A0]', ' '),
        # etc.
    ]

    # Replace characters in self.text
    text_i = self.text
    for old, new in patterns:
        text_i = re.sub(old, new, text_i)

    # Replace the same characters in all other objects
    queryset = Example.objects.all()
    for i, value in enumerate(patterns):
        old, new = value
        queryset = queryset.annotate(
            **{f'text_{i}': Func(F(f'text_{i - 1}' if i > 0 else 'text'),
                                 Value(old), Value(new), Value('g'),
                                 function='regexp_replace')})
    else:
        # Filter all where replaced texts are the same
        queryset = queryset.filter(**{f'text_{i}': text_i}).exclude(pk=self.pk)

    return queryset
Regex本身解决了大多数问题,因为可以一次替换多个字符,但我的模式相当复杂,所以我将它们拆分为列表,并用动态构建的字段名进行注释

话虽如此,如果我真的继续使用这个解决方案,或者更确切地说,在模型中添加一个字段来存储每个对象的“text_I”(替换已完成)值,那么我还不是100%,然后就这样做:

def variants(self):
    return Example.objects.filter(text_i=self.text_i).exclude(pk=self.pk)

我只需考虑“TrimeI i”是否足够稳定,以便在最初创建之后不必不断地更新它们。

确实如此,如果只替换一个或两个字符串,这是一个很好的解决方案。我必须删除至少五个字符,这样就有点复杂了。我一直在寻找类似Replace('text',Value('xyzw'),Value('')这样的东西,以使另一面更简单。无论如何,尽管这个精确的解决方案对我来说不是最优的,但对于其他类似的用例来说,它可能是一个很好的解决方案,您的回答也给了我一个如何继续的想法。我用的是Postgres,所以正则表达式可能是最好的选择。我会接受这个答案,谢谢你的帮助!这确实有效,如果您只有一个或两个字符串需要替换,那么这是一个很好的解决方案。我必须删除至少五个字符,这样就有点复杂了。我一直在寻找类似Replace('text',Value('xyzw'),Value('')这样的东西,以使另一面更简单。无论如何,尽管这个精确的解决方案对我来说不是最优的,但对于其他类似的用例来说,它可能是一个很好的解决方案,您的回答也给了我一个如何继续的想法。我用的是Postgres,所以正则表达式可能是最好的选择。我会接受这个答案,谢谢你的帮助!