Định dạng số trong mẫu django


154

Tôi đang cố gắng định dạng số. Ví dụ:

1     => 1
12    => 12
123   => 123
1234  => 1,234
12345 => 12,345

Đây là một điều khá phổ biến để làm nhưng tôi không thể tìm ra bộ lọc nào tôi nên sử dụng.

Chỉnh sửa: Nếu bạn có một cách Python chung để làm điều này, tôi rất vui khi thêm một trường được định dạng trong mô hình của tôi.


3
Hãy cẩn thận nếu người dùng mục tiêu của bạn cũng ở châu Âu. Một số nước châu Âu như Đức sử dụng, làm dấu thập phân.
tobltobs

Câu trả lời:


312

Ứng dụng nhân hóa đóng góp của Django thực hiện điều này:

{% load humanize %}
{{ my_num|intcomma }}

Hãy chắc chắn để thêm 'django.contrib.humanize'vào INSTALLED_APPSdanh sách của bạn trong settings.pytập tin.


17
Có một lý do tại sao một vài bộ lọc đơn giản không phải là một phần của bộ lọc tích hợp?
PawelRoman

8
@PawelRoman Để tránh tải một loạt các bộ lọc và thẻ hiếm khi được sử dụng (và do đó làm cho kết xuất mẫu nhanh hơn)
Maxime Lorant

Tôi đã thêm 'django.contrib.humanize' trong INSTALLED_APPS và cũng bao gồm {% load humanize%} trong mẫu của tôi và khởi động lại máy chủ. Tuy nhiên, khi tôi cố gắng sử dụng bộ lọc "intcomma", tôi gặp lỗi này - Bộ lọc không hợp lệ: 'intcomma' Dấu vết gỡ lỗi hiển thị 'django.contrib.humanize' được bao gồm trong settings.py. Điều gì có thể là vấn đề có thể?
Manish

1
Có câu trả lời cho vấn đề của riêng tôi ở đây - Tôi đã bao gồm {% load humanize%} trong mẫu cơ sở (vì tôi cần nó cho rất nhiều mẫu). Có vẻ như nó không hoạt động - khi tôi thêm nó vào các mẫu có liên quan, nó hoạt động tốt! :-)
Manish

Nếu nó không hoạt động, nó có thể là do nội địa hóa. Hãy thử {{my_num | intcomma: false}} trong trường hợp đó
Jose Cherian

105

Dựa trên các câu trả lời khác, để mở rộng điều này thành phao, bạn có thể làm:

{% load humanize %}
{{ floatvalue|floatformat:2|intcomma }}

Tài liệu: floatformat, intcomma.


59

Về giải pháp của Ned Batchelder, ở đây có 2 điểm thập phân và ký hiệu đô la. Cái này đi đâu đó nhưmy_app/templatetags/my_filters.py

from django import template
from django.contrib.humanize.templatetags.humanize import intcomma

register = template.Library()

def currency(dollars):
    dollars = round(float(dollars), 2)
    return "$%s%s" % (intcomma(int(dollars)), ("%0.2f" % dollars)[-3:])

register.filter('currency', currency)

Sau đó bạn có thể

{% load my_filters %}
{{my_dollars | currency}}

3
Lỗi trên mã trên, hãy thử điều này:>>> currency(0.99958) u'$0.00'
Ahsan

1
Mã này sẽ có trong tệp riêng của nó tại [your_project] / [your_app] / templatetags / [filtername] .py. Sau đó, nó sẽ được tải trong mẫu với {% load [filtername]%}. Xem docs.djangoproject.com/en/1.10/howto/custom-template-tags để biết thêm thông tin hữu ích và cụ thể.
mightypile

20

Hãy thử thêm dòng sau vào settings.py:

USE_THOUSAND_SEPARATOR = True

Điều này nên làm việc.

Tham khảo tài liệu .


cập nhật vào 2018-04-16:

Ngoài ra còn có một cách python để làm điều này:

>>> '{:,}'.format(1000000)
'1,000,000'

10
Hãy cẩn thận khi sử dụng này. Cũng sẽ định dạng số bằng url và các số khác mà bạn thêm vào mẫu
Christoffer

4
Tôi không thể nhấn mạnh đủ nhận xét của @Christoffer - trong các mẫu nơi id được hiển thị và sử dụng trong các liên kết, điều này có thể gây ra đau đầu lớn!
LaundroMat

Điều này không phù hợp với các mẫu Django
Ben

@Ben nào không phù hợp? "Con đường trăn" hay cờ phân cách ngàn trong cài đặt? cờ nghìn phân cách sẽ hoạt động tốt cho các mẫu Django. Phiên bản Django của bạn là gì?
carton.swing

1
Cách định dạng chuỗi (python) bởi vì bạn không thể sử dụng trực tiếp điều này trong các mẫu - bạn sẽ phải đặt nó trong thẻ mẫu (đây là một câu trả lời tốt), nhưng chỉ cần ném nó ra là một câu trả lời hoàn chỉnh.
Ben

11

Nếu bạn không muốn tham gia với các địa phương thì đây là một chức năng định dạng số:

def int_format(value, decimal_points=3, seperator=u'.'):
    value = str(value)
    if len(value) <= decimal_points:
        return value
    # say here we have value = '12345' and the default params above
    parts = []
    while value:
        parts.append(value[-decimal_points:])
        value = value[:-decimal_points]
    # now we should have parts = ['345', '12']
    parts.reverse()
    # and the return value should be u'12.345'
    return seperator.join(parts)

Tạo một bộ lọc mẫu tùy chỉnh từ chức năng này là không đáng kể.


10

Các nhân đạo giải pháp là tốt nếu trang web của bạn bằng tiếng Anh. Đối với các ngôn ngữ khác, bạn cần một giải pháp khác: Tôi khuyên bạn nên sử dụng Babel . Một giải pháp là tạo một thẻ mẫu tùy chỉnh để hiển thị số chính xác. Dưới đây là cách thực hiện: chỉ cần tạo tệp sau trong your_project/your_app/templatetags/sexify.py:

# -*- coding: utf-8 -*-
from django import template
from django.utils.translation import to_locale, get_language
from babel.numbers import format_number

register = template.Library()

def sexy_number(context, number, locale = None):
    if locale is None:
        locale = to_locale(get_language())
    return format_number(number, locale = locale)

register.simple_tag(takes_context=True)(sexy_number)

Sau đó, bạn có thể sử dụng thẻ mẫu này trong các mẫu của bạn như thế này:

{% load sexy_number from sexify %}

{% sexy_number 1234.56 %}
  • Đối với người dùng người Mỹ (locale en_US), điều này sẽ hiển thị 1,234,56.
  • Đối với người dùng tiếng Pháp (locale fr_FR), điều này sẽ hiển thị 1 234,56.
  • ...

Tất nhiên bạn có thể sử dụng các biến thay thế:

{% sexy_number some_variable %}

Lưu ý: các contextthông số hiện chưa được sử dụng trong ví dụ của tôi, nhưng tôi đặt nó ở đó để chứng minh rằng bạn có thể dễ dàng tinh chỉnh mẫu thẻ này để làm cho nó sử dụng bất cứ điều gì đó là trong các mẫu ngữ cảnh.


1
ngôn ngữ của tôi là 'pt_BR' và "intcomma" hoạt động ngay cả ở Brazil là sự tách biệt của '.' và không phải bởi ',' là floatvalue = 25000,35 {{floatvalue | intcomma}} kết quả trong 25000,35
Zokis

Bạn đúng, nhưng định dạng này không phù hợp với dải phân cách hàng nghìn (25.000,35 cho en_US và 25 000,35 cho fr_FR).
MiniQuark

4

Các ứng dụng nhân đạo Mời một tốt đẹp và một cách nhanh chóng để định dạng một số nhưng nếu bạn cần phải sử dụng một khác nhau tách từ dấu phẩy, nó đơn giản chỉ cần tái sử dụng mã từ ứng dụng nhân đạo , thay thế các dấu phân cách char, và tạo ra một bộ lọc tùy chỉnh . Ví dụ: sử dụng không gian làm dấu phân cách:

@register.filter('intspace')
def intspace(value):
    """
    Converts an integer to a string containing spaces every three digits.
    For example, 3000 becomes '3 000' and 45000 becomes '45 000'.
    See django.contrib.humanize app
    """
    orig = force_unicode(value)
    new = re.sub("^(-?\d+)(\d{3})", '\g<1> \g<2>', orig)
    if orig == new:
        return new
    else:
        return intspace(new)

Cảm ơn. Tôi cần một phiên bản chấm và đề nghị của bạn đã cứu tôi! Chúc mừng!
kstratis

3

Hơi lạc đề:

Tôi đã tìm thấy câu hỏi này trong khi tìm cách định dạng một số là tiền tệ, như vậy:

$100
($50)  # negative numbers without '-' and in parens

Tôi đã kết thúc việc làm:

{% if   var >= 0 %} ${{ var|stringformat:"d" }}
{% elif var <  0 %} $({{ var|stringformat:"d"|cut:"-" }})
{% endif %}

Bạn cũng có thể làm, ví dụ như {{ var|stringformat:"1.2f"|cut:"-" }}hiển thị dưới dạng $50.00(với 2 chữ số thập phân nếu đó là những gì bạn muốn.

Có lẽ hơi nghiêng về phía hacky, nhưng có lẽ người khác sẽ thấy nó hữu ích.


2

Chà, tôi không thể tìm thấy một cách Django, nhưng tôi đã tìm thấy một con trăn từ bên trong mô hình của mình:

def format_price(self):
    import locale
    locale.setlocale(locale.LC_ALL, '')
    return locale.format('%d', self.price, True)

Hmm - điều này đã được -1'd, không có lời giải thích - không có ích. Đối với những người nghĩ rằng câu trả lời là không chính xác theo một cách nào đó, xin vui lòng nói tại sao vì lợi ích của người trả lời và độc giả. Tôi cho rằng tôi không phải là người thích thiết lập miền địa phương (trong phạm vi toàn cầu), trong chức năng này (tác dụng phụ khó chịu của việc lấy tiền) - có thể giải thích -1.
Daniel Staple

Tôi đã làm thứ hai -1 - như được mô tả trong trước. nhận xét, thật s really not correct not giving any reason. Here itdễ dàng: Django đã có mẫu cụ thể (tương tự Jinja2 - hoặc đó là Jinja2) không cho phép các chức năng python tiêu chuẩn. Vì vậy, câu trả lời này không hữu ích chút nào. Hơn thế nữa, Django có các chức năng riêng quản lý việc này và viết bất cứ điều gì mới, những gì đang hoạt động thực sự không phải là ý tưởng hay ...
tomis

2
Tôi không đồng ý với các downvoters - đảm bảo giá trị được định dạng chính xác trong chức năng xem trước khi nó chạm vào mẫu có vẻ như là một cách tiếp cận hoàn toàn hợp lệ.
Paul Tomblin

1

Xin lưu ý rằng việc thay đổi ngôn ngữ là toàn quy trình và không an toàn cho luồng (iow., Có thể có tác dụng phụ hoặc có thể ảnh hưởng đến mã khác được thực thi trong cùng quy trình).

Đề xuất của tôi: kiểm tra gói Babel . Một số phương tiện tích hợp với các mẫu Django có sẵn.



1

Dựa trên câu trả lời của muhuk, tôi đã thực hiện string.formatphương pháp đóng gói thẻ python đơn giản này .

  • Tạo một templatetagsthư mục ứng dụng của bạn.
  • Tạo một format.pytập tin trên đó.
  • Thêm cái này vào nó:

    from django import template
    
    register = template.Library()
    
    @register.filter(name='format')
    def format(value, fmt):
        return fmt.format(value)
  • Tải nó trong mẫu của bạn {% load format %}
  • Sử dụng nó. {{ some_value|format:"{:0.2f}" }}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.