我想根据文本的长度过滤我的模型
MyModel.objects.filter(len(text) > 10)
其中text是MyModel模型中的Char或Text字段
Answers:
这将是更好和更快,如果你只是增加一列,预先计算(memoizes)文本的长度。
例如
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`
text
。每次修改文本时都会更新。因此,当我们查询模型时,我们可以根据我们在save
方法中预先计算出的文本长度进行过滤。
对于Django> = 1.8,您可以使用Length函数,它是CHAR_LENGTH()
MySQL或LENGTH()
其他一些数据库的@Pratyush函数:
from django.db.models.functions import Length
qs = MyModel.objects.annotate(text_len=Length('text_field_name')).filter(
text_len__gt=10)
text_len__gt=10
到第一位(order_by
)。有什么提示吗?
text_len
注释中你可以使用任何其他数据库的相同方式领域,因此它可以在order_by
或Sum
或什么的。要以减小的文本长度顺序对结果进行排序并返回长度值:MyModel.objects.annotate(text_len=Length('text_field_name')).order_by('-text_len').values_list('text_len', flat=True)
。
Length
Transform的全局注册。
Sum
。在许多情况下,这也非常重要。我遇到了一种情况,我需要预先检查查询可能返回的最大数据大小,这不会使服务器的内存不足,并且这种情况的一种变体效果很好。
Length
运算符之前相同的行数。因此,它称为转换或映射。聚合减少了记录数。映射没有。
另一种方法是:
MyModel.objects.extra(where=["CHAR_LENGTH(text) > 300"])
如果文本长度也超过255个字符,则可以使用此选项。
LENGTH(..)
。
通过将内置函数注册Length
为用于查找的Transform,可以为Django> = 1.9提供一个不错的解决方案CharField
。
在项目中注册一次转换。(最好的地方可能是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)
请参阅docs中与Length作为转换的完全相同的示例。
它适用于所有后端,由LENGTH()
大多数后端和CHAR_LENGTH()
MySQL编译。然后,它会自动为CharField的所有子类注册,例如为EmailField注册。将TextField
必须单独注册。注册名称“长度”是安全的,因为转换名称永远不会被同名字段名或相关字段名遮蔽或遮蔽。
唯一的缺点可能是可读性之谜:“长度”从何而来?(查找是全局的,但是幸运的是,如果对可读性有用,则可以将其安全地重复注册到更多模块中,而不会在查询运行时产生任何开销。)
其他类似的有价值的解决方案是上面的滚刀,如果注册计数并且如果不重复使用类似的查询,则较短。
您可以使用正则表达式过滤器来搜索特定长度的文本:
MyModel.objects.filter(text__regex = r'.{10}.*')
注意:对于MySQL,最大长度值为255。否则将引发异常:
DatabaseError: (1139, "Got error 'invalid repetition count(s)' from regexp")
Using raw strings (e.g., r'foo' instead of 'foo') for passing in the regular expression syntax is recommended.
我会在您的应用服务器上解决该问题,而不会对数据库征税。您可以通过以下方式做到这一点:
models_less_than_ten = []
mymodel = MyModel.objects.all()
for m in mymodel:
if len(m.text) > 10:
models_less_than_ten.append(m)