Я хотел бы отфильтровать мою модель на основе длины текста Что-то вроде
MyModel.objects.filter(len(text) > 10)
где текст является Char или текстовым полем в модели MyModel
Я хотел бы отфильтровать мою модель на основе длины текста Что-то вроде
MyModel.objects.filter(len(text) > 10)
где текст является Char или текстовым полем в модели MyModel
Было бы намного лучше и быстрее, если бы вы просто добавили столбец, который предварительно вычисляет (запоминает) длину текста.
например.
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`
Для Django >= 1.8 вы можете использовать Функция длины, которая является @Pratyush CHAR_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 символов.
Вы можете использовать фильтр регулярных выражений для поиска текста определенной длины:
MyModel.objects.filter(text__regex = r'.{10}.*')
Предостережение: для MySQL максимальное значение длины - 255. В противном случае создается исключение:
DatabaseError: (1139, "Got error 'invalid repetition count(s)' from regexp")
Хорошее решение для Django >= 1.9 возможно благодаря регистрации встроенной функции Length
в качестве Преобразования для CharField
поиска, (см. точно такой же пример в документах для Length as a transform)
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()
для большинства бэкэнд и CHAR_LENGTH()
для MySQL. Затем он регистрируется для всех подклассов CharField автоматически, например. для EmailField. TextField
необходимо зарегистрировать отдельно. Безопасно регистрировать имя "длина", потому что имя трансформирования никогда не может быть затенено или затенено одинаковым именем поля или связанным с ним именем поля.
Единственным недостатком может быть головоломка для чтения: откуда появилась "длина"? (Поиск является глобальным, но то же самое может быть, к счастью, безопасно зарегистрировано повторно в большем количестве модулей, если оно полезно для удобства чтения, без каких-либо возможных накладных расходов во время выполнения запроса.)
Другим аналогичным ценным решением является hobs выше, чем короче, если учетная запись подсчитывается и если аналогичный запрос не используется повторно.
Я бы решил проблему на вашем сервере приложений, а не облагал налоговую базу данных. Вы можете сделать это:
models_less_than_ten = []
mymodel = MyModel.objects.all()
for m in mymodel:
if len(m.text) > 10:
models_less_than_ten.append(m)