Django 查询集的自然排序
Natural sort on Django Queryset
我正在开发一个列出按产品代码排序的一系列产品的系统。产品代码由两个字母组成,后跟一个数字,例如 EG1.
我目前通过简单的
对这些产品进行排序
Product.objects.order_by('product_code')
,
然而,由于可以有多个数字产品代码(例如 EG12),因此这些代码将排在单个数字代码之前。
即 EG1、EG11、EG12、EG13 ... EG19、EG2、EG20 等
我知道在产品代码中添加前导零可以解决此问题(即 EG01 而不是 EG1),但由于已经有印刷文献和使用 EG1 的现有网站,所以这不是一个选项。
有没有办法解决这个问题,以正确的顺序显示这些产品?
我认为这里的实现 (https://github.com/nathforge/django-naturalsortfield) 应该可行。这种方法的主要优点是它不在 python 中进行排序,而是在数据库中进行排序,因此即使在大型数据集上它也能表现良好,但需要一些额外的存储空间。
您必须更改模型以包含 product_code__sort 字段
class MyModel(models.Model):
title = models.CharField(max_length=255)
title_sort = NaturalSortField('title')
其中 NaturalSortField 定义为
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
试试这个
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)
我正在开发一个列出按产品代码排序的一系列产品的系统。产品代码由两个字母组成,后跟一个数字,例如 EG1.
我目前通过简单的
对这些产品进行排序Product.objects.order_by('product_code')
,
然而,由于可以有多个数字产品代码(例如 EG12),因此这些代码将排在单个数字代码之前。 即 EG1、EG11、EG12、EG13 ... EG19、EG2、EG20 等
我知道在产品代码中添加前导零可以解决此问题(即 EG01 而不是 EG1),但由于已经有印刷文献和使用 EG1 的现有网站,所以这不是一个选项。
有没有办法解决这个问题,以正确的顺序显示这些产品?
我认为这里的实现 (https://github.com/nathforge/django-naturalsortfield) 应该可行。这种方法的主要优点是它不在 python 中进行排序,而是在数据库中进行排序,因此即使在大型数据集上它也能表现良好,但需要一些额外的存储空间。
您必须更改模型以包含 product_code__sort 字段
class MyModel(models.Model):
title = models.CharField(max_length=255)
title_sort = NaturalSortField('title')
其中 NaturalSortField 定义为
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
试试这个
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)