Formatieren Sie Zahlen in Django-Vorlagen

153

Ich versuche Zahlen zu formatieren. Beispiele:

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

Es scheint ziemlich üblich zu sein, aber ich kann nicht herausfinden, welchen Filter ich verwenden soll.

Bearbeiten: Wenn Sie eine generische Python-Methode haben, füge ich gerne ein formatiertes Feld in mein Modell ein.

Oli
quelle
3
Seien Sie vorsichtig, wenn sich Ihre Zielbenutzer auch in Europa befinden. Einige europäische Länder wie Deutschland verwenden als Dezimalstelle.
tobltobs

Antworten:

310

Djangos Beitrag zur Humanisierung bewirkt Folgendes:

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

Stellen Sie sicher, dass Sie 'django.contrib.humanize'Ihrer INSTALLED_APPSListe in der settings.pyDatei hinzufügen .

Ned Batchelder
quelle
17
Gibt es einen Grund, warum diese wenigen einfachen Filter nicht Teil der integrierten Filter sind?
PawelRoman
8
@ PawelRoman Um das Laden einer Reihe von Filtern und Tags zu vermeiden, die selten verwendet werden (und so das Rendern der Vorlage zu beschleunigen)
Maxime Lorant
Ich habe 'django.contrib.humanize' in INSTALLED_APPS hinzugefügt und auch {% load humanize%} in meine Vorlage aufgenommen und den Server neu gestartet. Wenn ich jedoch versuche, den Filter "intcomma" zu verwenden, wird folgende Fehlermeldung angezeigt: - Ungültiger Filter: 'intcomma' Der Debug-Trace zeigt 'django.contrib.humanize' in settings.py. Was könnte das mögliche Problem sein?
Manish
1
Ich habe hier eine Antwort auf mein eigenes Problem erhalten - ich hatte {% load humanize%} in die Basisvorlage aufgenommen (da ich es für viele Vorlagen benötige). Es scheint, dass es nicht funktioniert - als ich es in den entsprechenden Vorlagen hinzugefügt habe, hat es gut funktioniert! :-)
Manish
Wenn es nicht funktioniert, liegt es möglicherweise an der Lokalisierung. Versuchen Sie in diesem Fall {{my_num | intcomma: False}}
Jose Cherian
105

Aufbauend auf anderen Antworten können Sie Folgendes tun, um dies auf Floats auszudehnen:

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

Dokumentation: floatformat, intcomma.

Vinod Kurup
quelle
59

In Bezug auf die Lösung von Ned Batchelder gibt es hier 2 Dezimalstellen und ein Dollarzeichen. Das geht irgendwo somy_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)

Dann kannst du

{% load my_filters %}
{{my_dollars | currency}}
Dave Aaron Smith
quelle
3
Fehler am obigen Code, versuchen Sie dies:>>> currency(0.99958) u'$0.00'
Ahsan
1
Dieser Code sollte in einer eigenen Datei unter [your_project] / [your_app] / templatetags / [filtername] .py abgelegt werden. Es sollte dann mit {% load [filtername]%} in die Vorlage geladen werden. Weitere hilfreiche und spezifische Informationen finden Sie unter docs.djangoproject.com/de/1.10/howto/custom-template-tags .
mächtiger
20

Versuchen Sie, die folgende Zeile in settings.py hinzuzufügen:

USE_THOUSAND_SEPARATOR = True

Das sollte funktionieren.

Siehe Dokumentation .


Update am 16.04.2018:

Es gibt auch eine Python-Methode, um dies zu tun:

>>> '{:,}'.format(1000000)
'1,000,000'
carton.swing
quelle
10
Seien Sie vorsichtig, wenn Sie dies verwenden. Formatiert auch Zahlen in URLs und anderen, die Sie der Vorlage hinzufügen
Christoffer
4
Ich kann den Kommentar von @Christoffer nicht genug betonen - in Vorlagen, in denen IDs gerendert und in Links verwendet werden, kann dies zu großen Kopfschmerzen führen!
LaundroMat
Dies ist nicht geeignet für Django-Vorlagen
Ben
@ Ben was ist nicht angebracht? "the python way" oder das Tausendertrennzeichen in den Einstellungen? Das Tausendertrennzeichen sollte für Django-Vorlagen gut funktionieren. Was ist die Version Ihres Django?
carton.swing
1
Das Zeichenfolgenformat (die Python-Methode), da Sie dies nicht direkt in Vorlagen verwenden können - Sie müssten dies in ein Vorlagen-Tag einfügen (was eine gute Antwort ist), aber es ist als vollständige Antwort wenig hilfreich, dies nur wegzuwerfen.
Ben
11

Wenn Sie sich nicht mit Gebietsschemas beschäftigen möchten, finden Sie hier eine Funktion zum Formatieren von Zahlen:

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)

Das Erstellen eines benutzerdefinierten Vorlagenfilters aus dieser Funktion ist trivial.

Muhuk
quelle
10

Die Humanisierungslösung ist in Ordnung, wenn Ihre Website auf Englisch ist. Für andere Sprachen benötigen Sie eine andere Lösung: Ich empfehle die Verwendung von Babel . Eine Lösung besteht darin, ein benutzerdefiniertes Vorlagen-Tag zu erstellen, um Zahlen richtig anzuzeigen. So geht's: Erstellen Sie einfach die folgende Datei in 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)

Dann können Sie dieses Vorlagen-Tag in Ihren Vorlagen wie folgt verwenden:

{% load sexy_number from sexify %}

{% sexy_number 1234.56 %}
  • Für einen amerikanischen Benutzer (Gebietsschema en_US) werden 1.234,56 angezeigt.
  • Für einen französischen Benutzer (Gebietsschema fr_FR) wird 1 234,56 angezeigt.
  • ...

Natürlich können Sie stattdessen Variablen verwenden:

{% sexy_number some_variable %}

Hinweis: Der contextParameter wird derzeit in meinem Beispiel nicht verwendet, aber ich habe ihn dort abgelegt, um zu zeigen, dass Sie dieses Vorlagen-Tag einfach optimieren können, damit es alles verwendet, was sich im Vorlagenkontext befindet.

MiniQuark
quelle
1
Mein Gebietsschema ist 'pt_BR' und "intcomma" funktioniert sogar in Brasilien, da die Trennung durch '.' und nicht durch ',' als floatvalue = 25000.35 {{floatvalue | intcomma}} ergibt 25000.35
Zokis
Sie haben Recht, aber dieses Format ist für das Tausendertrennzeichen nicht geeignet (25.000,35 für en_US und 25.000,35 für fr_FR).
MiniQuark
4

Die Humanize-App bietet eine schöne und schnelle Möglichkeit, eine Zahl zu formatieren. Wenn Sie jedoch ein anderes Trennzeichen als das Komma verwenden müssen, können Sie den Code aus der Humanize-App einfach wiederverwenden , das Trennzeichen ersetzen und einen benutzerdefinierten Filter erstellen . Verwenden Sie beispielsweise Leerzeichen als Trennzeichen:

@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)
Enis Afgan
quelle
Vielen Dank. Ich brauchte eine Punktversion und dein Vorschlag hat mich gerettet! Prost!
Kstratis
3

Etwas abseits des Themas:

Ich habe diese Frage gefunden, als ich nach einer Möglichkeit gesucht habe, eine Zahl als Währung zu formatieren:

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

Am Ende tat ich:

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

Sie können dies auch tun, z. B. {{ var|stringformat:"1.2f"|cut:"-" }}als $50.00(mit 2 Dezimalstellen, wenn Sie dies wünschen).

Vielleicht etwas hackig, aber vielleicht findet es jemand anderes nützlich.

Felix Böhme
quelle
2

Nun, ich konnte keinen Django-Weg finden, aber ich habe einen Python-Weg in meinem Modell gefunden:

def format_price(self):
    import locale
    locale.setlocale(locale.LC_ALL, '')
    return locale.format('%d', self.price, True)
Oli
quelle
Hmm - das war -1 ohne Erklärung - nicht hilfreich. Für diejenigen, die denken, dass die Antwort in irgendeiner Weise falsch ist, sagen Sie bitte, warum zum Nutzen des Antwortenden und der Leser. Ich bin wohl kein Fan davon, das Gebietsschema (das global erreichbar ist) in dieser einen Funktion (unangenehmer Nebeneffekt beim Erhalten der Währung) festzulegen - was das -1 erklären könnte.
Danny Staple
Ich habe die zweite -1 gemacht - wie in vorher beschrieben. Kommentar, es ist s really not correct not giving any reason. Here iteinfach: Django hat eine spezifische Vorlage (ähnlich wie Jinja2 - oder Jinja2), die keine Standard-Python-Funktionen zulässt. Diese Antwort ist also überhaupt nicht nützlich. Darüber hinaus hat Django eigene Funktionen, die dies verwalten und alles Neue schreiben, was funktioniert. Das ist wirklich keine gute Idee ...
Tomis
2
Ich bin mit den Downvotern nicht einverstanden - es scheint ein absolut gültiger Ansatz zu sein, sicherzustellen, dass der Wert in der Ansichtsfunktion richtig formatiert ist, bevor er auf die Vorlage trifft.
Paul Tomblin
1

Beachten Sie, dass das Ändern des Gebietsschemas prozessweit und nicht threadsicher ist (iow., Kann Nebenwirkungen haben oder anderen Code beeinflussen, der innerhalb desselben Prozesses ausgeführt wird).

Mein Vorschlag: Schauen Sie sich das Babel- Paket an. Es stehen einige Möglichkeiten zur Integration in Django-Vorlagen zur Verfügung.

zgoda
quelle
1

Basierend auf Muhuk Antwort habe ich dieses einfache Tag gemacht, das die Python- string.formatMethode einkapselt .

  • Erstellen Sie einen templatetagsin Ihrem Anwendungsordner.
  • Erstellen Sie eine format.pyDatei darauf.
  • Fügen Sie dies hinzu:

    from django import template
    
    register = template.Library()
    
    @register.filter(name='format')
    def format(value, fmt):
        return fmt.format(value)
  • Laden Sie es in Ihre Vorlage {% load format %}
  • Benutze es. {{ some_value|format:"{:0.2f}" }}
Geckos
quelle