2016-12-16 4 views
0

Я хочу заказать QuerySet с помощью charfield с числами в нем. У меня есть этот код:Как я могу заказать QuerySet в Django с помощью charfield с числами?

MyTable.objects.all().order_by('my_char_field') 

Есть некоторые примеры "my_char_field":

"ver3", "ver10", "x5.1 (1)", "ver4", "x5.1 (2)" 

Результат заказа с выше код:

"ver10", "ver3", "ver4", "x5.1 (1)", "x5.1 (2)" 

Но порядок что я хочу:

"ver3", "ver4", "ver10", "x5.1 (1)", "x5.1 (2)" 

Как я могу получить естественный заказ?

+1

Всегда ли это начинается с 'ver'? – AKS

+0

Являются ли они единственными вариациями? Будет ли это поле символов всегда заканчиваться рядом цифр и начинаться с ряда алфавитов? Может ли версия иметь точку внутри, например. 'ver 2.1.2'? – AKS

+0

@AKS Версия может иметь точку внутри, а также разные начала и окончания – MouTio

ответ

5

Это похоже на проблему хранения данных. Это становится гораздо проще, если изменить структуру

version_type = models.CharField() 
version_num = models.FloatField() 
version_revision = models.SmallIntegerField(null=True) 

unique_together = [('version_type', 'version_num', 'version_revision')] 

.order_by('version_type', 'version_num', 'version_revision') 

данных Это также позволит решить ваш следующий вопрос «как я могу эффективно получить все версии типа„версии“?»

+1

Да, это путь. – e4c5

2

Хотя можно выполнить выборку и выполнить сортировку на стороне клиента, вы также можете использовать функцию Substr, чтобы сделать это со стороны сервера.

from django.db.models.functions import Substr 

MyTable.objects.all().order_by(Substr('my_char_field',3)) 

Update:

я работал над другим обновлением к ответу, когда вопрос был обновлен еще раз !! Следующие неполные, но вы можете построить на нем.

MyTable.objects.annotate(
    sort_field=Case(
     When(my_char_field__start_with='ver', Then=Substr(my_char_field,3), 
     When(my_char_field__start_with='x', Then=Substr(my_char_field,1), 
     default = my_char_field) 

).order_by('sort_field) 

Вам нужно будет использовать функцию Cast, чтобы отличить sort_field к int. Это будет длинный запрос!

+0

. Я уверен, что вы не смотрели обновленное сообщение?И это не будет работать для '10', потому что это строка. – AKS

+0

Я написал этот ответ, не увидев обновление. Думаю, мне придется добавить обновление. – e4c5

+1

@ Дайте слишком много исправлений на вопрос, но новое обновление должно получить OP на треке – e4c5

0

Как упоминалось в @AKS, это может быть неэффективно для сортировки в памяти. Как только у вас будет большой стол, и вы хотите вывести только первую страницу результатов сортировки. Затем вам нужно вытащить каждую строку из базы данных, прежде чем вы сможете сделать сортировку.


Возможно, вы захотите добавить еще одно поле, которое заполняется из поля сортировки при добавлении новой записи. На этот раз вы можете настроить сортировку базы данных для вас.

Something From Vem3456 to Vem6543