我想根据文本的长度过滤我的模型
MyModel.objects.filter(len(text) > 10)
其中 text 是 MyModel 模型中的 Char 或 Text 字段
我想根据文本的长度过滤我的模型
MyModel.objects.filter(len(text) > 10)
其中 text 是 MyModel 模型中的 Char 或 Text 字段
对于 Django >= 1.8,您可以使用Length 函数,这是 @PratyushCHAR_LENGTH()
在 MySQL 或LENGTH()
其他一些数据库的底层:
from django.db.models.functions import Length
qs = MyModel.objects.annotate(text_len=Length('text_field_name')).filter(
text_len__gt=10)
另一种方法是:
MyModel.objects.extra(where=["CHAR_LENGTH(text) > 300"])
这也可以用于文本长度超过 255 个字符的情况。
通过将内置函数注册为用于查找Length
的转换,可以为 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)
在Length as a transform的文档中查看完全相同的示例。
它适用于所有后端,由LENGTH()
大多数后端和CHAR_LENGTH()
MySQL 编译。然后自动为 CharField 的所有子类注册,例如为 EmailField。TextField
必须单独注册。注册名称“length”是安全的,因为转换名称永远不会被同名的字段名称或相关字段名称遮蔽或遮蔽。
唯一的缺点可能是可读性难题:“长度”从何而来?(查找是全局的,但幸运的是,如果对可读性有用,同样可以安全地在更多模块中重复注册,而不会在查询运行时产生任何可能的开销。)
其他类似有价值的解决方案是上面的hobs,如果注册计数并且不重复使用类似的查询,则该解决方案会更短。
您可以使用正则表达式过滤器来搜索特定长度的文本:
MyModel.objects.filter(text__regex = r'.{10}.*')
警告:对于 MySQL,最大长度值为 255。否则抛出异常:
DatabaseError: (1139, "Got error 'invalid repetition count(s)' from regexp")
我会在您的应用服务器上解决问题,而不是对您的数据库征税。您可以通过以下方式执行此操作:
models_less_than_ten = []
mymodel = MyModel.objects.all()
for m in mymodel:
if len(m.text) > 10:
models_less_than_ten.append(m)
如果您只添加一个预先计算(记忆)文本长度的列,那会更好更快。
例如
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`