Django Queryset上的自然排序 [英] Natural sort on Django Queryset

查看:197
本文介绍了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

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 example EG1.

I currently sort these products by doing a simple

Product.objects.order_by('product_code'),

however as there can be multiple digit product codes (for example EG12), these will come out above ahead of the single digit codes. i.e EG1, EG11, EG12, EG13 ... EG19, EG2, EG20 etc

I know that adding leading zeros to the product codes will fix this (i.e EG01 rather than EG1) but as there is already printed literature and an existing site using EG1 this is not an option.

Is there a way to fix this to show these products in the correct order?

解决方案

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

这篇关于Django Queryset上的自然排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆