Sort objects by a substring of a model field in django
Question:
Im trying to find best solution to sort through all Machine objects in my db and find last deviceSerialNo used.
deviceSerialNo is a character field and has a structure like this: AB12-12344.
My task is to sort all Machine objects by a substring of deviceSerialNo field(everything after ‘-‘ in deviceSerialNo.
My current solution that kind of works
last = Machine.objects.all().order_by('-deviceSerialNo').first().deviceSerialNo
or
last2 = Machine.objects.all().order_by('-deviceSerialNo').annotate(search_index=StrIndex('deviceSerialNo', V('-'))).first().deviceSerialNo
Can someone help me sort it as I mentioned above?
Answers:
You can order by a field created with annotate:
from django.db.models import IntegerField, Value as V
from django.db.models.functions import Cast, StrIndex, Substr
last = (
Machine.objects.annotate(
part=Cast(Substr("deviceSerialNo", StrIndex("deviceSerialNo", V("-"))), IntegerField())
)
.order_by("part")
.first()
.deviceSerialNo
)
Just like you had we start by getting the index of the -
character:
StrIndex('deviceSerialNo', V('-'))
We then take use Substr
to get the second part including the -
character:
Substr("deviceSerialNo", StrIndex("deviceSerialNo", V("-")))
Then we cast it to an IntegerField, sort and get the first object. Note: We can get the first object as the integer cast of "-12344"
is a negative number.
If number have multiple – and want to extract out number from reverse then try following. AB-12-12344
Output: 12344
qs.annotate(
r_part=Reverse('number')
).annotate(
part=Reverse(
Cast(
Substr("r_part", 1, StrIndex("r_part", V("-")))
),
IntegerField()
)
)
thanks
You can sort the objects using the extra() function:
your_objects = Machine.objects.all()
your_objects = your_objects.extra(select={‘str_deviceSerialNo’:’SUBSTRING("deviceSerialNo",initial_char,last_char)’}).order_by(‘str_deviceSerialNo’)
It worked for me.
Im trying to find best solution to sort through all Machine objects in my db and find last deviceSerialNo used.
deviceSerialNo is a character field and has a structure like this: AB12-12344.
My task is to sort all Machine objects by a substring of deviceSerialNo field(everything after ‘-‘ in deviceSerialNo.
My current solution that kind of works
last = Machine.objects.all().order_by('-deviceSerialNo').first().deviceSerialNo
or
last2 = Machine.objects.all().order_by('-deviceSerialNo').annotate(search_index=StrIndex('deviceSerialNo', V('-'))).first().deviceSerialNo
Can someone help me sort it as I mentioned above?
You can order by a field created with annotate:
from django.db.models import IntegerField, Value as V
from django.db.models.functions import Cast, StrIndex, Substr
last = (
Machine.objects.annotate(
part=Cast(Substr("deviceSerialNo", StrIndex("deviceSerialNo", V("-"))), IntegerField())
)
.order_by("part")
.first()
.deviceSerialNo
)
Just like you had we start by getting the index of the -
character:
StrIndex('deviceSerialNo', V('-'))
We then take use Substr
to get the second part including the -
character:
Substr("deviceSerialNo", StrIndex("deviceSerialNo", V("-")))
Then we cast it to an IntegerField, sort and get the first object. Note: We can get the first object as the integer cast of "-12344"
is a negative number.
If number have multiple – and want to extract out number from reverse then try following. AB-12-12344
Output: 12344
qs.annotate(
r_part=Reverse('number')
).annotate(
part=Reverse(
Cast(
Substr("r_part", 1, StrIndex("r_part", V("-")))
),
IntegerField()
)
)
thanks
You can sort the objects using the extra() function:
your_objects = Machine.objects.all()
your_objects = your_objects.extra(select={‘str_deviceSerialNo’:’SUBSTRING("deviceSerialNo",initial_char,last_char)’}).order_by(‘str_deviceSerialNo’)
It worked for me.