Natural sort on Django Queryset

后端 未结 2 1615
再見小時候
再見小時候 2021-01-12 10:09

I am working on a system that lists out a range of products sorted by their product code. The product codes are made up of two letters for the followed by a number, for exam

相关标签:
2条回答
  • 2021-01-12 10:17

    I think the implementation here (https://github.com/nathforge/django-naturalsortfield) should work. The main advantage of this method is that it doesn't do the sorting in python but in the database so it'll perform well even on large datasets, at the cost of some additional storage.

    You have to change your model to include a product_code__sort field

    class MyModel(models.Model):
        title = models.CharField(max_length=255)
        title_sort = NaturalSortField('title')
    

    where the NaturalSortField is defined as

    class NaturalSortField(models.CharField):
        def __init__(self, for_field, **kwargs):
            self.for_field = for_field
            kwargs.setdefault('db_index', True)
            kwargs.setdefault('editable', False)
            kwargs.setdefault('max_length', 255)
            super(NaturalSortField, self).__init__(**kwargs)
    
        def pre_save(self, model_instance, add):
            return self.naturalize(getattr(model_instance, self.for_field))
    
        def naturalize(self, string):
            def naturalize_int_match(match):
                return '%08d' % (int(match.group(0)),)
    
            string = string.lower()
            string = string.strip()
            string = re.sub(r'^the\s+', '', string)
            string = re.sub(r'\d+', naturalize_int_match, string)
    
            return string
    
    0 讨论(0)
  • 2021-01-12 10:24

    Try this

    def alphanumeric_sort(objects_list, sort_key):
        """ Sort a list of objects by a given key
        This function sort a list of objects by a given
        key common across the objects
        Sorting can be implemented on keys that are either
        alphabets, integers or both
        """
        convert = lambda text: int(text) if text.isdigit() else text
        alphanum_key = lambda key: [
            convert(c) for c in re.split("([0-9]+)", getattr(key, sort_key))
        ]
        return sorted(objects_list, key=alphanum_key)
    
    0 讨论(0)
提交回复
热议问题