django基于文本长度过滤

时间:2012-09-07 08:08:21

标签: django

我想根据文本的长度过滤我的模型 像

这样的东西
MyModel.objects.filter(len(text) > 10)

其中text是MyModel模型中的Char或Text字段

6 个答案:

答案 0 :(得分:138)

对于Django> = 1.8,你可以使用Length function,这是MySQL的@Pratyush的CHAR_LENGTH()或者其他一些数据库的LENGTH()

from django.db.models.functions import Length
qs = MyModel.objects.annotate(text_len=Length('text_field_name')).filter(
    text_len__gt=10)

答案 1 :(得分:54)

另一种方式是:

MyModel.objects.extra(where=["CHAR_LENGTH(text) > 300"])

这可用于文本长度超过255个字符的地方。

答案 2 :(得分:27)

您可以使用正则表达式过滤器搜索特定长度的文本:

MyModel.objects.filter(text__regex = r'.{10}.*')

警告:对于MySQL,最大长度值为255.否则抛出异常:

DatabaseError: (1139, "Got error 'invalid repetition count(s)' from regexp")

答案 3 :(得分:17)

通过将内置函数Length注册为CharField查找的转换,可以为Django> = 1.9提供一个很好的解决方案。

注册项目中的转换一次。 (最好的地方可能是models.py。)

from django.db.models import CharField
from django.db.models.functions import Length

CharField.register_lookup(Length, 'length')

使用

result = MyModel.objects.filter(text__length__gt=10)

Length as a transform的文档中查看完全相同的示例。

它适用于所有后端,由LENGTH()为大多数后端编译,由CHAR_LENGTH()编译为MySQL。然后自动为CharField的所有子类注册,例如对于EmailField。 TextField必须单独注册。注册名称“length”是安全的,因为变换名称永远不会被同名的字段名称或相关字段名称着色或加阴影。

唯一的缺点可能是可读性难题:“长度”来自何处? (查找是全局的,但如果在可读性方面有用,则可以在更多模块中重复安全地注册,但在查询运行时没有任何可能的开销。)

其他同样有价值的解决方案是上面的hobs,如果注册计数并且重复使用类似的查询,则更短。

答案 4 :(得分:-1)

如果只添加预先计算(记忆)长度的列,那么会更快 文本。

e.g。

class MyModel(models.Model):
    text = models.TextField()
    text_len = models.PositiveIntegerField()

     def save(self, *args, **kwargs):
         self.text_len = len(self.text)
         return super(MyModel, self).save(*args, **kwargs)

MyModel.objects.filter(text_len__gt = 10)     # Here text_len is pre-calculated by us on `save`

答案 5 :(得分:-3)

我会解决您的应用服务器上的问题,而不是对您的数据库征税。您可以通过以下方式执行此操作:

models_less_than_ten = []
mymodel = MyModel.objects.all()
for m in mymodel:
    if len(m.text) > 10:
          models_less_than_ten.append(m)