我有一个这样的模型:
class Product(models.Model):
name = models.CharField(max_length=5)
名称示例:A-123
是否有办法过滤此名称字段,以便我可以输入连字符或将其省略,并获得相同的结果?例如,查询“A-123”和“A123”将返回相同的项目。使用常规过滤器,我仅在执行“A-123”时得到结果。
如果不是,最好的解决方案是制作一个 on_save 触发器来填充辅助“可搜索”字段吗?
这将是我最初的想法,但我担心这会效率低下。
我考虑过的另一种方法是拉出所有对象,然后循环并删除连字符以找到匹配项,但我再次担心性能问题/效率。
最佳答案
添加具有规范化名称的字段将是一个明智的解决方案,尽管我会通过覆盖 Product
模型上的 .save()
来填充它。
class Product(models.Model):
name = models.CharField(max_length=5)
normalized_name = models.CharField(max_length=5)
def save(self, *args, **kwargs):
self.normalized_name = self.normalize_name(name)
super().save(*args, **kwargs)
@classmethod
def normalize_name(cls, name):
return name.replace('-', '') # Maybe also remove spaces?
Product.objects.filter(normalized_name=Product.normalize_name('A-123'))
Product.objects.filter(normalized_name=Product.normalize_name('A123'))
如果您在多个地方使用它,您可能需要创建一个自定义管理器以避免代码重复:
class ProductManager(models.Manager):
def filter_by_normalized_name(name):
normalized_name = Product.normalize_name('A-123')
return self.get_queryset().filter(normalized_name=normalized_name)
class Product(models.Model):
...
objects = ProductManager
Product.objects.filter_by_normalized_name('A123')
Product.objects.filter_by_normalized_name('A-123')
或者,如果 Product.name
始终具有相同的结构,您可以标准化您的搜索词。
例如如果您知道该名称始终以连字符作为第二个字符:
if search_term[1] != '-':
search_term = f"{search_term[0]}-{search_term[1:]}"
要获得更精细的解决方案,您可能需要研究使用 PostgreSQL 或 ElasticSearch 的全文搜索。
关于python - Django:有没有办法过滤模型并忽略存储的连字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59684315/