Django şablonlarındaki sayıları biçimlendirme


153

Sayıları biçimlendirmeye çalışıyorum. Örnekler:

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

Yapması oldukça yaygın bir şey gibi gözüküyor, ancak hangi filtreyi kullanmam gerektiğini anlayamıyorum.

Düzenleme: Bunu yapmak için genel bir Python yolu varsa, modelime biçimlendirilmiş bir alan eklemek için mutluyum.


3
Hedef kullanıcılarınız da Avrupa'daysa dikkatli olun. Almanya gibi bazı Avrupa ülkeleri ondalık işareti olarak kullanmaktadır.
tobltobs

Yanıtlar:


313

Django'nun katkıda bulunan insancıllaştırma uygulaması bunu yapar:

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

Eklemeyi unutmayın 'django.contrib.humanize'sizin için INSTALLED_APPSlisteye settings.pydosyası.


17
Bu birkaç basit filtrenin yerleşik filtrelerin bir parçası olmamasının bir nedeni var mı?
PawelRoman

8
@PawelRoman Nadiren kullanılan bir grup filtre ve etiketin yüklenmesini önlemek (ve böylece şablonun daha hızlı oluşturulmasını sağlamak)
Maxime Lorant

INSTALLED_APPS içine 'django.contrib.humanize' ekledim ve ayrıca şablonuma {% load humanize%} ekledim ve sunucuyu yeniden başlattım. Ancak, "intcomma" filtresi kullanmaya çalıştığımda, bu hatayı alıyorum - Geçersiz filtre: 'intcomma' Hata ayıklama izlemesi, settings.py içinde bulunan 'django.contrib.humanize' öğesini gösterir. Olası sorun ne olabilir?
Manish

1
Burada kendi sorunuma cevap var - temel şablon {% load humanize%} dahil (çünkü çok sayıda şablon için ihtiyaç). Çalışmıyor gibi görünüyor - ilgili şablonlara eklediğimde, iyi çalıştı! :-)
Manish

Çalışmazsa, yerelleştirmeden kaynaklanıyor olabilir. Bu durumda {{my_num | intcomma: False}} 'yı deneyin
Jose Cherian

105

Diğer cevaplara dayanarak, bunu yüzenlere genişletmek için şunları yapabilirsiniz:

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

Dokümantasyon: floatformat, intcomma.


59

Ned Batchelder'in çözümü ile ilgili olarak, burada 2 ondalık puan ve bir dolar işareti ile. Bu gibi bir yere gidiyormy_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)

O zaman yapabilirsin

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

3
Yukarıdaki kod üzerinde hata, şunu deneyin:>>> currency(0.99958) u'$0.00'
Ahsan

1
Bu kod, [dosya_ projeniz] / [uygulamanız] / şablon etiketler / [dosyaadı] .py adresindeki kendi dosyasında olmalıdır. Ardından şablona {% load [filtername]%} ile yüklenmelidir. Daha yararlı ve spesifik bilgiler için docs.djangoproject.com/tr/1.10/howto/custom-template-tags adresine bakın .
mightypile

20

Settings.py dosyasına aşağıdaki satırı eklemeyi deneyin:

USE_THOUSAND_SEPARATOR = True

Bu çalışmalı.

Belgelere başvurun .


2018-04-16'da güncelleme:

Bu şeyi yapmanın bir python yolu da var:

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

10
Bunu kullanırken dikkatli olun. Ayrıca, şablona eklediğiniz url ve diğer sayıları da biçimlendirir
Christoffer

4
@Christoffer'ın yorumunu yeterince vurgulayamıyorum - kimliklerin oluşturulduğu ve bağlantılarda kullanıldığı şablonlarda, bu büyük baş ağrılarına neden olabilir!
LaundroMat

Bu Django şablonları için uygun değildir
Ben

@Ben hangisi uygun değil? "python yolu" veya ayarlarda bin ayırıcı bayrak? bin ayırıcı bayrak Django şablonları için iyi çalışır olmalıdır. Django sürüm nedir?
karton.swing

1
Bunu doğrudan şablonlarda kullanamayacağınız için dize biçimi (python) yolu - bunu bir şablon etiketine (iyi bir yanıttır) koymanız gerekir, ancak bunu atmak tam bir cevap olarak çok az kullanılır.
Ben

11

Burada yerel ayarlara dahil olmak istemiyorsanız, sayıları biçimlendiren bir işlev vardır:

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)

Bu işlevden özel bir şablon filtresi oluşturmak önemsizdir.


10

İnsanileştirmek web sitesi İngilizce olarak ise çözüm gayet iyi. Diğer diller için başka bir çözüme ihtiyacınız var: Babel kullanmanızı tavsiye ederim . Bir çözüm, sayıları düzgün bir şekilde görüntülemek için özel bir şablon etiketi oluşturmaktır. Bunu nasıl yapacağınız aşağıda açıklanmıştır 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)

Ardından bu şablon etiketini şablonlarınızda şu şekilde kullanabilirsiniz:

{% load sexy_number from sexify %}

{% sexy_number 1234.56 %}
  • Amerikalı bir kullanıcı için (locale en_US) bu 1.234.56 değerini görüntüler.
  • Fransız bir kullanıcı için (yerel ayar fr_FR), bu 1 234,56 görüntüler.
  • ...

Elbette bunun yerine değişkenleri kullanabilirsiniz:

{% sexy_number some_variable %}

Not:context Parametre anda benim örnekte kullanılan, ama bunu kolaylıkla şablon bağlamında olan her şeyi kullanmak için bu şablon etiketini çimdik orada göstermek koymak değildir.


1
yerel ayarım 'pt_BR' ve "intcomma" Brezilya'da bile 'ile' ayrılıyor. ve ',' değil floatvalue = 25000.35 {{floatvalue | intcomma}} olmak 25000.35 ile sonuçlanır
Zokis

Haklısınız, ancak bu biçim binlerce ayırıcı için uygun değil (en_US için 25.000,35 ve fr_FR için 25 000,35).
MiniQuark

4

İnsanileştirmek uygulaması teklifler güzel ve bir sayı biçimlendirme hızlı bir yolu ancak virgülden bir ayırıcı farklı kullanım gerekiyorsa, hiç 's basit sadece yeniden insanileştirmek uygulamasından kod , ayırıcı kömürü yerine ve özel bir filtre oluşturmak . Örneğin, ayırıcı olarak boşluk kullanın :

@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)

Teşekkürler. Bir nokta sürümüne ihtiyacım vardı ve öneriniz beni kurtardı! Şerefe!
kstratis

3

Biraz konu dışı:

Bir sayıyı para birimi olarak biçimlendirmenin bir yolunu ararken bu soruyu buldum:

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

Sonunda şunu yaptım:

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

Ayrıca, ör. {{ var|stringformat:"1.2f"|cut:"-" }} istediğiniz gibi $50.00ise 2 ondalık basamakla) görüntülemek için .

Belki biraz acayip tarafta, ama belki başka biri yararlı bulacaktır.


2

Bir Django yolu bulamadım, ama modelimin içinden bir python yolu buldum:

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

Hmm - bu açıklama olmadan -1'd oldu - yararsızdır. Cevabın bir şekilde yanlış olduğunu düşünenler için lütfen cevaplayıcının ve okuyucuların yararına neden olduğunu söyleyin. Ben bu bir fonksiyonda (para birimi alma hoş olmayan yan etkisi) - -1 açıklayabilir yerel ayarı (hayran ulaşılabilir küresel) ayarlama hayranı değilim.
Danny Staple

İkinci -1'i yaptım - önceki bölümde açıklandığı gibi. yorum, bu s really not correct not giving any reason. Here itkolay: Django, standart python işlevlerine izin vermeyen belirli bir şablona (Jinja2'ye benzer - veya Jinja2'ye) sahiptir. Yani bu cevap hiç de kullanışlı değil. Dahası, Django'nun bunu yöneten ve yeni bir şey yazan kendi işlevleri var, gerçekten iyi bir fikir değil ...
tomis

2
Ben downvoters ile aynı fikirde değilim - değerin şablon isabet önce görünüm işlevinde düzgün biçimlendirilmiş olduğundan emin olmak mükemmel geçerli bir yaklaşım gibi görünüyor.
Paul Tomblin

1

Yerel ayarın değiştirilmesinin işlem çapında olduğunu ve iş parçacığı için güvenli olmadığını unutmayın (iow., Yan etkilere sahip olabilir veya aynı işlemde yürütülen diğer kodu etkileyebilir).

Benim önerim: Babil paketine bir göz at. Django şablonlarıyla entegrasyon için bazı araçlar mevcuttur.



1

Muhuk cevabına dayanarak bu basit etiketi sarmalayan python string.formatyöntemini yaptım .

  • Oluşturmak templatetags sizin uygulama klasörüne de.
  • format.pyÜzerinde bir dosya oluşturun .
  • Buna ekleyin:

    from django import template
    
    register = template.Library()
    
    @register.filter(name='format')
    def format(value, fmt):
        return fmt.format(value)
  • Şablonunuza yükleyin {% load format %}
  • Kullanın. {{ some_value|format:"{:0.2f}" }}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.