Django - 按CharField值长度过滤查询集

Ger*_*ard 14 python django data-migration django-south

鉴于我有一个基于CharFieldor CharField的模型字段的遗留模型,如:

class MyModel(models.Model):
    name = models.CharField(max_length=1024, ...)
    ...
Run Code Online (Sandbox Code Playgroud)

我需要进行迁移以使其具有max_length最大值.255.首先,我正在编写一个datamigration使任何超过255个字符的值适应即将到来schemamigration的修复列的最大长度,我将在此工作后立即执行.

问题是我有一个非常大的数据集,我知道并非所有行都包含超过255个字符的值MyModel.name,我想考虑我的迁移只有那些人.

是否有任何方法(使用)django ORM仅过滤满足此条件的对象?就像是:

MyModel.objects.filter(name__len__gte=255)
Run Code Online (Sandbox Code Playgroud)

会很棒,但我相信这是不可能的,或者至少它不是那么简单.

有人知道完成此查询的任何方法吗?

谢谢!

BBT*_*BBT 18

'最近'的Django版本具有内置的django.db.models.functions.Length查找/转换功能,因此您可以:

MyModel.objects.annotate(length=Length('text')).filter(length__gt=254)
Run Code Online (Sandbox Code Playgroud)

请参阅https://docs.djangoproject.com/en/1.11/ref/models/database-functions/#length

老答案:

我想你必须选择:

在查询集上使用'extra':

MyModel.objects.extra(where=["CHAR_LENGTH(text) > 254"])
Run Code Online (Sandbox Code Playgroud)

或者滥用正则表达式查找,我假设这会慢一些:

MyModel.objects.filter(text__regex = r'^.{254}.*')
Run Code Online (Sandbox Code Playgroud)

  • 我正在使用 PostgreSQL,发现正则表达式是我的救星。 (2认同)

Lor*_*uma 6

如果你发现你使用了很多额外的正则表达式,按照@ 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)
Run Code Online (Sandbox Code Playgroud)

此后,我可以对"mycolname"进行级联查找,如下所示:

from utils.db import *

queryset.filter(mycolname__len__gte=10)
Run Code Online (Sandbox Code Playgroud)