2010-04-02 20 views
51

Ich bin gespannt, welches wäre besser als Währungsfeld? Ich werde einfache Operationen wie Differenzbildung durchführen, den Prozentsatz zwischen alten und neuen Preisen. Ich plane, zwei Ziffern nach der Null zu halten (dh 10.50) und die meiste Zeit, wenn diese Ziffern Null sind, werde ich diese Zahlen verstecken und es als "10" anzeigenDjango: FloatField oder DecimalField für Währung?

PS: Währung ist NICHT dollarbasiert :)

Antwort

89

Verwenden Sie immer DecimalField für Geld. Selbst einfache Operationen (Addition, Subtraktion) sind nicht immun gegen Rundungsprobleme schweben:

>>> 10.50 - 0.20 
10.300000000000001 

>>> Decimal('10.50') - Decimal('0.20') 
Decimal('10.30') 
+4

'>>> 10.50 - 0.20' in Python 2.7 erhalten' 10.3'. – Rockallite

+0

Welp, Mist. Ich werde viele Daten von meinem FloatField-Feld/Spalten zu DecimalField migrieren ... – teewuane

+0

Höchste Zeit haben wir eine "nicht Gleitkomma für Geld" analog zu bobince http://stackoverflow.com/a/1732454/ 604511 – aitchnyu

6

edit: Das Satchmo-Projekt ist nicht mehr aktiv, so bei diesen Alternativen einen Blick Währung für den Umgang mit


Die Django-basierte Satchmo Project hat ein CurrencyField und CurrencyWidget, die einen Blick wert sind.

Schauen Sie sich die satchmo_utils App-Verzeichnis für die Quelle

32

Die Antwort auf die Frage richtig ist, aber einige Benutzer auf diese Frage stolpern die Differenz zwischen dem DecimalField und dem FloatField zu erfahren. Das Float-Rundung-Problem, das Seth aufwirft, ist ein Währungsproblem.

Die Django Docs Staaten

The FloatField class is sometimes mixed up with the DecimalField class. Although they both represent real numbers, they represent those numbers differently. FloatField uses Python’s float type internally, while DecimalField uses Python’s Decimal type. Read more here .

Hier sind weitere Unterschiede zwischen den beiden Feldern:

DecimalField:

  • DecimalFields muss ein 'decimal_places' definieren und ein Attribut 'max_digits'.
  • Sie erhalten zwei Freiformvalidierungen, die hier von den oben genannten erforderlichen Attributen enthalten sind, dh Wenn Sie max_digits auf 4 setzen und eine Dezimalzahl eingeben, die 4,00000 (5 Ziffern) ist, erhalten Sie diesen Fehler: Stellen Sie sicher, dass es keine gibt mehr als 4 Ziffern insgesamt.
  • Sie erhalten auch eine ähnliche Form Validierung für Dezimalstellen (die in den meisten Browsern auch am Frontend mit dem Schritt Attribut auf dem Eingabefeld validiert. Wenn Sie Dezimalstellen = 1 und geben Sie 0,001 als Wert ein einen Fehler, dass der Minimalwert 0,1 sein muss.
  • Gibt ein decimal.Decimal Typ ist
  • verfügt nicht über die zusätzliche Validierung als DecimalField
  • Mit einem Dezimal-Typ, Rundung ist auch für Sie behandelt wegen die erforderlichen Attribute, die wie oben beschrieben gesetzt werden müssen.So aus der Shell, wenn Sie
  • In der Datenbank (Postgresql) ist das DecimalField speichern d als numeric (max_digits, decimal_laces) Typ und Speicher wird als "main" von oben Beispiel der Typ numerisch ist (4,1)

Mehr zu DecimalField from the Django Docs.

FloatField:

  • Gibt den eingebauten Schwimmertyp,
  • Keine intelligente Rundung und Ausgaben in Rundungs ​​tatsächlich zur Folge haben kann, wie in Seths Antwort beschrieben.
  • Hat das zusätzliche Formular-Validierung nicht, dass Sie von DecimalField bekommen
  • In der Datenbank (postgresql) wird die FloatField als „double precision“ Typ gespeichert und Lagerung wird als „plain“

Mehr unter FloatField from the Django Docs.

gilt für beide:

  • Beide Felder aus dem "Feld" Klasse erweitern und kann 'leer', 'null', 'verbose_name', 'Name', 'primary_key', 'max_length' akzeptieren, 'unique', 'db_index', 'rel', 'default', 'editierbar', 'serialize', 'unique_for_date', 'unique_for_month', 'unique_for_year', 'Auswahlmöglichkeiten', 'help_text', 'db_column', 'db_tablespace ',' auto_created ',' validators ',' error_messages 'Attribute, wie alle Felder die sich von "Field" erstrecken.
  • Das Standardformular Widget für beide Felder ist ein TextInput.

ich auf diese Frage kam, als die Differenz zwischen den beiden Feldern suchen, so denke ich, das diejenigen, die in der gleichen Situation helfen :)

UPDATE: Um die Frage zu beantworten, ich glaube, Sie wegkommen entweder um die Währung darzustellen, obwohl Dezimal viel besser passt. Es gibt ein Rundungsproblem, wenn es zu Floaten zählt, also müssen Sie round(value, 2) verwenden, um Ihre Float-Darstellung auf zwei Dezimalstellen gerundet zu halten. Hier ist ein schnelles Beispiel:

>>> round(1.13 * 50 + .01, 2) 
56.51 

Sie können immer noch Probleme mit Float und Runde bekommen. Wie hier sehen wir es auf einen Wert von 5 abrundet:

>>> round(5.685, 2) 
5.68 

Aber in diesem Fall wird es aufrunden:

>>> round(2.995, 2) 
3.0 

Es hat alles zu tun, wie der Schwimmer im Speicher abgelegt . Siehe here.

Verwandte Themen