我有一个像这样的模型:
class Product(models.Model):
name = models.CharField(max_length=5)
名称的示例如下:A-123
无论如何,有没有过滤此名称字段的方法,所以我可以输入连字符或不使用连字符,并得到相同的结果?例如,查询“ A-123”和“ A123”将返回相同的项目。使用常规过滤器,只有在执行“ A-123”时才能得到结果。
如果不是,最好的解决方案是使on_save触发器填充第二个“可搜索”字段吗?
那将是我最初的想法,但我担心这样会导致效率低下。
我考虑过的另一种方法是拉出所有对象,然后遍历并删除连字符以找到匹配项,但是我再次担心性能问题/效率。
添加一个字段的标准化名称将是一个明智的解决方案,但我会通过覆盖填充它.save()
的Product
模型。
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进行全文搜索。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句