Search code examples
pythondjangosortingormdjango-orm

Sort version number of format 1.1.1 in Django


I have a Django model with a release_version char field that stores version information in the format 1.1.1 (e.g., 1.2.3). I need to sort a queryset based on this version field so that versions are ordered correctly according to their major, minor, and patch numbers.

class Release(models.Model):
    file_name = models.CharField(max_length=255)
    release_version = models.CharField(max_length=16)

Using the default order_by gives the result in lexicographic order and it sorts 1.10.0 before 1.2.0 when sorting ascending. The solution seems to be that I can annotate the major, minor and patch version and then sort based on these three fields. The issue in this is that I am not able to figure out how to separate this version into major, minor and patch numbers. I am using postgresql.


Solution

  • To properly sort release_version field, you can break it down into major, minor, and patch numbers and sort them accordingly.

    You can achieve this by using Django's annotate() feature, which allows you to annotate fields to perform operations on them, and SplitPart from PostgreSQL, which can split strings based on a delimiter.

    This is the code example.

    from django.db.models import F, Value
    from django.db.models.functions import Cast
    from django.db.models.expressions import Func
    from django.db.models import IntegerField
    
    queryset = Release.objects.annotate(
        major=Cast(Func(F('release_version'), Value('.'), Value(1), function='split_part'), IntegerField()),
        minor=Cast(Func(F('release_version'), Value('.'), Value(2), function='split_part'), IntegerField()),
        patch=Cast(Func(F('release_version'), Value('.'), Value(3), function='split_part'), IntegerField())
    ).order_by('major', 'minor', 'patch')
    

    I hope this will solve your issue.