【问题标题】:Django - Filter queryset by CharField value lengthDjango - 按 CharField 值长度过滤查询集
【发布时间】:2014-06-14 14:17:21
【问题描述】:

鉴于我有一个带有基于 CharField 或 CharField 的模型字段的旧模型,例如:

class MyModel(models.Model):
    name = models.CharField(max_length=1024, ...)
    ...

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

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

django ORM 有什么方法可以只过滤满足这个条件的对象吗?比如:

MyModel.objects.filter(name__len__gte=255)

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

有人知道完成这个查询的方法吗?

谢谢!

【问题讨论】:

标签: python django django-south data-migration


【解决方案1】:

'Recent' 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

旧答案:

我认为你必须选择:

在查询集上使用“额外”:

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

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

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

【讨论】:

【解决方案2】:

如果您发现自己使用了很多额外的和正则表达式,按照@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)

【讨论】:

    猜你喜欢
    • 2018-09-26
    • 1970-01-01
    • 2013-04-20
    • 2018-10-28
    • 1970-01-01
    • 2012-05-18
    • 2019-02-09
    • 1970-01-01
    • 2020-08-22
    相关资源
    最近更新 更多