繁体   English   中英

在 MultiSelectField 中按一位数字过滤

[英]filtering by one-digit number in MultiSelectField

我有MyModel

class MyModel(models.Model):
    ELEMENTS_CHOICES = Choices(
        (1, 'element1'),
        (2, 'element2'),
        (3, 'element3'),
        (4, 'element4'),
        (10, 'element10'),
        (12, 'element12'),
    )
    elements = MultiSelectField(
        _('elements'),
        choices=ELEMENTS_CHOICES,
        blank=True,
    )

我还有一些MyModel对象,其elements值如下:

obj1.elements = ['1', '2', '3', '10', '12']
obj2.elements = ['1', '3', '10', '12']
obj3.elements = ['1', '3', '10']
obj4.elements = ['2']

如何过滤此字段值?

我尝试使用的过滤器是:

search_id = 2
MyModel.objects.filter(elements_icontains=search_id)

MyModel字段选项中出现两位数之前是可以的。 现在它返回obj1obj2 (因为12在列表中,并且它包含 2 作为它的一部分)和obj4

我想只搜索具有2数字的值并仅获得obj1obj4作为结果。 目前,结果是包含212的对象。

过滤此字段的正确方法是什么?

将数据以逗号分隔的列表形式存储在数据库中并不是一种很好的技术,通常建议不要这样做。 您的用例本身就意味着您正面临这个问题。 如果可行,您应该重新设计您的 model 架构(推荐)并使用ForeignKeyManyToManyField来实现您的目标。

如果不幸由于某种原因无法更改此架构,您只能解决使用正则表达式来查询您的数据库:

import re


search_id = 2
filter_term = r'\b%s\b' % re.escape(str(search_id)) # \b is word boundary in regex
MyModel.objects.filter(elements__iregex=filter_term)

您应该为这个特定问题建议适当的数据库规范化。

如果您仍然发现自己必须在不更改数据库的情况下使用 go,您可以使用两种方式过滤正则表达式,甚至更好地使用string_to_array() ,因为它可以被索引

这将要求您在一行中执行raw()查询

WHERE 2 = any(string_to_array(elements));

然后,您可以添加功能索引以增加性能优势

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM