Как обрезать/вырезать ведущие пробелы из StringField для представления списка в Django/Mongodb?
Хочу отсортировать данные по именам, но к сожалению есть много данных с пробелами, поэтому rest_framework.filters.OrderingFilter
не работает должным образом. В моем проекте используются Mongo, DRF.
Моя модель:
from mongoengine import DynamicDocument, fields
class Book(DynamicDocument):
name = fields.StringField(required=True)
description = fields.StringField(blank=True, null=True)
meta = {
'collection': 'books',
'strict': False,
}
Мое мнение:
from rest_framework.filters import OrderingFilter
from rest_framework_mongoengine import viewsets
from core.serializers import BookSerializer
from core.models import Book
class BookViewSet(viewsets.ModelViewSet):
serializer_class = BookSerializer
queryset = Book.objects.all()
filter_backends = [OrderingFilter]
ordering_fields = ['name']
ordering = ['name']
У кого-нибудь есть идеи, как это решить?
Попытка аннотирования кверисета:
from django.db.models import F, Func
...
class BookViewSet(viewsets.ModelViewSet):
...
def get_queryset(self):
queryset = self.queryset.annotate(name_lower=Func(F('name'), function='LOWER'))
В mongoDB существует операция агрегации $trim, которую можно использовать для санации строковых данных, если вы хотите удалить только ведущие пробелы, вы можете использовать $ltrim ...
Если кто-то имеет дело с mongoengine, вы можете решить эту проблему с помощью queryset.aggregate()
class BookViewSet(viewsets.ModelViewSet):
serializer_class = BookSerializer
queryset = Book.objects.all()
def get_queryset(self):
queryset = self.queryset
pipeline = [
{
'$project': {
'id': {'$toString': '$_id'},
'name': 1,
'ltrim_lower_name': {'$ltrim': {'input': {'$toLower': '$name'}}},
'description': 1,
}
},
{'$sort': {'ltrim_lower_name': 1}}
]
return queryset.aggregate(pipeline)
Используется python 'trim_lower_name': {'$ltrim': {'input': {'$toLower': '$name'}}}
потому что нужна сортировка без учета регистра
Найдите еще одно решение для этого вопроса
utils.py:
collation = dict(
locale='en',
caseLevel=False,
caseFirst='off',
strength=1,
numericOrdering=True,
alternate='shifted',
maxVariable='space',
backwards=False,
)
В views.py:
class BookViewSet(viewsets.ModelViewSet):
serializer_class = BookSerializer
queryset = Book.objects.all()
def get_queryset(self):
queryset = self.queryset
return queryset.collation(collation)