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