自定义Django计数过滤

时间:2015-10-23 22:12:33

标签: django django-models django-views django-filter

很多网站都会显示:

  • “1.8K页”而不是“1,830页”

  • “43.2M页”而不是“43,400,123页”

有没有办法在Django中执行此操作?

例如,以下代码将在查询集中生成量化的对象数量(即3,123):

Books.objects.all().count()

有没有办法添加自定义计数过滤器来返回“3.1K页面”而不是“3,123页?”

提前谢谢!

1 个答案:

答案 0 :(得分:0)

首先,我不会做任何改变Django ORM部分工作方式的事情。如果您只打算在一个地方使用它,可以在两个地方完成这项工作 - 在前端进行。话虽如此,有很多方法可以实现这一结果。只是为了提出一些想法,你可以在你的模型上写一个调用count的属性,然后将其转换为对后端更具人性化的东西。如果你想在前端做到这一点,你可能想找到一个可以进行转换的JavaScript库。

稍后我将从我的计算机编辑此内容并添加该属性的示例。

编辑:要回答你的评论,更容易实现,取决于你在python和JavaScript中的技能。我更喜欢python,所以我可能会在模型的某个地方进行。

Edit2:我写了一个例子,向您展示如何在基础模型或需要这些数字的模型上进行classmethod。我发现了一个名为humanize的python包,我把它们的函数转换成可读的并修改了一下,允许成千上万,并取出了一些超大数转换。

def readable_number(value, short=False):
    # Modified from the package `humanize` on pypy.
    powers = [10 ** x for x in (3, 6, 9, 12, 15, 18)]
    human_powers = ('thousand', 'million', 'billion', 'trillion', 'quadrillion')
    human_powers_short = ('K', 'M', 'B', 'T', 'QD')
    try:
        value = int(value)
    except (TypeError, ValueError):
        return value

    if value < powers[0]:
        return str(value)
    for ordinal, power in enumerate(powers[1:], 1):
        if value < power:
            chopped = value / float(powers[ordinal - 1])
            chopped = format(chopped, '.1f')
            if not short:
                return '{} {}'.format(chopped, human_powers[ordinal - 1])
            return '{}{}'.format(chopped, human_powers_short[ordinal - 1])


class MyModel(models.Model):
    @classmethod
    def readable_count(cls, short=True):
        count = cls.objects.all().count()
        return readable_number(count, short=short)


print(readable_number(62220, True))  # Returns '62.2K'
print(readable_number(6555500))  # Returns '6.6 million'

我会将readable_number粘贴到某种类型的工具中,然后将其导入模型文件中。一旦你拥有了它,你可以在你的前端任何地方坚持使用该字符串。

您可以使用MyModel.readable_count()来获取该值。如果你想在MyModel.objects.readable_count()下使用它,你需要为你的模型制作一个自定义对象管理器,但这有点高级。