2008-12-06 98 views
109

Estoy tratando de formatear números. Ejemplos:Números de formato en plantillas django

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

Se parece una cosa bastante común que hacer, pero no puedo averiguar qué filtro se supone que debo usar.

Editar: Si tiene una forma genérica de Python para hacer esto, me complace agregar un campo formateado en mi modelo.

+3

Tenga cuidado si sus usuarios objetivo también están en Europa. Algunos países europeos como Alemania usan, como marca decimal. – tobltobs

Respuesta

214

Django contribuyeron humanize aplicación hace lo siguiente:

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

Asegúrese de añadir a su lista de 'django.contrib.humanize'INSTALLED_APPSsettings.py en el archivo.

+10

¿Hay alguna razón por la cual estos pocos filtros simples no sean parte de los filtros incorporados? – PawelRoman

+3

humanize está integrado, es parte de django. – jononomo

+4

@PawelRoman Para evitar la carga de un montón de filtros y etiquetas raramente utilizados (y hacer que la plantilla sea más rápida) –

2

Bueno, yo no podía encontrar una manera de Django, pero encontré una forma de pitón desde el interior de mi modelo:

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

Hmm - esto ha sido -1'd, sin explicación - inútil. Para aquellos que piensan que la respuesta es incorrecta de alguna manera, por favor digan por qué en beneficio del que responde y de los lectores. Supongo que no soy partidario de establecer la configuración regional (que es de alcance global), en esta función (desagradable efecto secundario de obtener la moneda), lo que podría explicar el -1. –

+0

Hice el segundo -1 - como se describe en prev. comentar, no es correcto no dar ninguna razón. Aquí es fácil: Django tiene una plantilla específica (similar a Jinja2 - o es Jinja2) que no permite las funciones estándar de Python. Entonces esta respuesta no es útil en absoluto. Además, Django tiene sus propias funciones para gestionar esto y escribir algo nuevo. Lo que funciona realmente no es una buena idea ... – tomis

+2

No estoy de acuerdo con los que votan negativamente: asegurarse de que el valor esté formateado correctamente en la función de vista antes de que aparezca. como un enfoque perfectamente válido. –

11

Si no quiere involucrarse con lugares que aquí hay una función que formatos números:

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) 

Creación de un custom template filter de esta función es trivial.

+0

+1 para el enlace de filtro de plantilla personalizada. – Shawn

1

Tenga en cuenta que cambiar la configuración regional es todo el proceso y no es seguro para subprocesos (por ejemplo, puede tener efectos secundarios o puede afectar a otros códigos ejecutados dentro del mismo proceso).

Mi proposición: echa un vistazo al paquete Babel. Algunos medios de integración con las plantillas de Django están disponibles.

53

En cuanto a la solución de Ned Batchelder, aquí está con 2 puntos decimales y un signo de dólar.

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

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

A continuación, puede

{{my_dollars | currency}} 
+2

Error en el código anterior, intente esto: '>>> moneda (0.99958) u '$ 0.00'' – Ahsan

+1

Gracias @Ahsan. Fijo. –

+0

dólares? ¡extraño! –

3

El humanize app ofrece una agradable y una forma rápida de dar formato a un número, pero si es necesario utilizar un separador diferente de la coma, es muy sencillo simplemente reutilizar the code from the humanize app, reemplace el separador char, y create a custom filter. Por ejemplo, utilice espacio como separador:

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

Gracias. ¡Necesitaba una versión de punto y tu sugerencia me salvó! ¡Aclamaciones! – kstratis

75

Basándose en otras respuestas, extender esto a los flotadores, que puede hacer:

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

La solución humanize está bien si su sitio web está en Inglés. Para otros idiomas, necesita otra solución: recomiendo usar Babel. Una solución es crear una etiqueta de plantilla personalizada para mostrar los números correctamente. Así es como: basta con crear el siguiente archivo en 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) 

continuación, puede utilizar esta etiqueta plantilla en sus plantillas de la siguiente manera:

{% load sexy_number from sexify %} 

{% sexy_number 1234.56 %} 
  • Para un usuario americano (localidad en_US) esta muestra 1,234.56.
  • Para un usuario francés (configuración fr_FR), muestra 1 234,56.
  • ...

Por supuesto se pueden utilizar variables en su lugar:

{% sexy_number some_variable %} 

Nota: el parámetrocontext actualmente no se utiliza en mi ejemplo, pero me puso ahí para demostrar que puede ajustar fácilmente esta etiqueta de plantilla para hacer que use cualquier cosa que esté en el contexto de la plantilla.

+1

mi configuración regional es 'pt_BR' y "intcomma" funciona incluso en Brasil siendo la separación por '.' y no por '' siendo floatValue = 25000.35 {{floatValue | intcomma}} da lugar a 25.000,35 – Zokis

+0

Tienes razón, pero este formato no es apropiado en relación con el separador de miles (25,000.35 para en_US y 25 000,35 para fr_FR). – MiniQuark

3

ligeramente fuera de tema:

me encontré con esta pregunta en la búsqueda de una manera de dar formato a un número como moneda, así:

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

que terminé haciendo:

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

También podría hacer, por ejemplo {{ var|stringformat:"1.2f"|cut:"-" }} para mostrar como $50.00 (con 2 cifras decimales, si eso es lo que quiere

quizás un poco en el lado hacky, pero tal vez alguien más lo encontrarán útil

7

Trate de añadir la siguiente línea en settings.py..:

USE_THOUSAND_SEPARATOR = True 

Esto debería funcionar.

Consulte documentation.

+0

Tenga cuidado al usar esto. También formateará números en urls y otros que agregue a la plantilla – Christoffer

0

Basado en la respuesta muhuk Hice esta simple etiqueta que encapsula el método python string.format.

  • Cree un templatetags en la carpeta de la aplicación de su.
  • Cree un archivo format.py en él.
  • Añadir esto a él:

    from django import template 
    
    register = template.Library() 
    
    @register.filter(name='format') 
    def format(value, fmt): 
        return fmt.format(value) 
    
  • cargarlo en su plantilla {% load format %}
  • usarlo. {{ some_value|format:"{:0.2f}" }}