Django - 按CharField值长度过滤查询集
我有一个旧的模型,里面有一个叫做 CharField
的字段,或者是基于 CharField
的字段,像这样:
class MyModel(models.Model):
name = models.CharField(max_length=1024, ...)
...
我需要进行数据迁移,把这个字段的最大长度设置为255个字符。首先,我要写一个 datamigration
,让所有超过255个字符的值适应接下来的 schemamigration
,这样才能修复这个字段的最大长度,等这个步骤完成后我会继续进行。
问题是,我的数据量非常非常大,而且我知道并不是所有的行都包含超过255个字符的 MyModel.name
,我只想在迁移时考虑那些确实超过的行。
有没有办法通过django的ORM来筛选出符合这个条件的对象呢?比如说:
MyModel.objects.filter(name__len__gte=255)
这样做会很好,但我觉得这可能不太可能,或者至少没有那么简单。
有没有人知道怎么实现这个查询呢?
谢谢!
2 个回答
7
如果你发现自己在使用很多额外的东西和正则表达式,按照@BBT的建议,我接着实现了如下的转换:
# utils.db
from django.db.models import Transform
from django.db.models import CharField
class CharacterLength(Transform):
lookup_name = 'len'
def as_sql(self, compiler, connection):
lhs, params = compiler.compile(self.lhs)
return "LENGTH(%s)" % lhs, params
CharField.register_lookup(CharacterLength)
之后,我可以对“mycolname”进行级联查找,方法如下:
from utils.db import *
queryset.filter(mycolname__len__gte=10)
28
最近的 Django 版本里有一个内置的功能叫做 django.db.models.functions.Length
,这样你就可以直接使用它来计算字符串的长度:
MyModel.objects.annotate(length=Length('text')).filter(length__gt=254)
你可以查看这个链接了解更多信息:https://docs.djangoproject.com/en/1.11/ref/models/database-functions/#length
旧的回答:
我觉得你有两个选择:
第一种是使用查询集中的 'extra' 功能:
MyModel.objects.extra(where=["CHAR_LENGTH(text) > 254"])
第二种是使用正则表达式查找,不过我想这样会比较慢:
MyModel.objects.filter(text__regex = r'^.{254}.*')