Bidang model django apa yang terbaik untuk digunakan untuk mewakili jumlah dolar AS?

104

Saya perlu menyimpan sejumlah US $ dolar dalam bidang model Django. Apa jenis bidang model terbaik untuk digunakan? Saya harus dapat meminta pengguna memasukkan nilai ini (dengan pengecekan kesalahan, hanya menginginkan angka yang akurat menjadi sen), memformatnya untuk keluaran ke pengguna di tempat yang berbeda, dan menggunakannya untuk menghitung angka lain.

MikeN
sumber

Jawaban:

167

Sebuah lapangan desimal adalah pilihan yang tepat untuk nilai mata uang.

Ini akan terlihat seperti:

credit = models.DecimalField(max_digits=6, decimal_places=2)
cukup keras
sumber
100
Kecuali Anda ingin mewakili utang nasional, dalam hal ini max_digits harus> 20
Bron Davies
4
decimal_places = 2 belum tentu benar jika Anda membutuhkannya untuk mendukung mata uang lain. Beberapa mata uang memiliki tiga tempat desimal, dan Bitcoin memiliki angka 8 rejan.
Lie Ryan
2
Saya rasa contoh ini benar hampir untuk semua mata uang. Untuk merepresentasikan mata uang sebagai Bitcoin, saya pikir lebih baik menggunakan bidang integer untuk menyimpan jumlah dalam satoshi, dan kemudian menunjukkannya kepada pengguna akhir dalam representasi yang Anda inginkan (BTC, mBTC, dll)
jion
Kecuali Anda ingin mewakili hutang nasional venezuela, dalam mata uang nasional Venezuela, dalam hal ini Anda memerlukan 21 max_digits
Luis Sieira
@LieRyan itu benar. Kita harus memperhatikan jenis "mata uang" modern untuk mencegah modifikasi db di masa mendatang. Tidak ada pelanggaran untuk penggunaan kutipan.
enchance
35

Jawaban lain adalah 100% benar tetapi tidak terlalu praktis karena Anda masih harus mengelola keluaran, pemformatan, dll secara manual.

Saya akan menyarankan menggunakan django-money :

from djmoney.models.fields import MoneyField
from django.db import models


def SomeModel(models.Model):
    some_currency = MoneyField(
        decimal_places=2,
        default=0,
        default_currency='USD',
        max_digits=11,
    )

Bekerja secara otomatis dari template:

{{ somemodel.some_currency }}

Keluaran:

$123.00

Ini memiliki backend yang kuat melalui python-money dan pada dasarnya ini adalah pengganti drop-in untuk bidang desimal standar.

Michael Thompson
sumber
(dengan pengecekan kesalahan, hanya menginginkan angka yang akurat menjadi sen), memformatnya untuk keluaran ke pengguna di tempat yang berbeda, dan menggunakannya untuk menghitung angka lain. Untuk kasus seperti itu, penggunaan DecimalFieldlebih praktis. Dan saya yakin ini diterapkan untuk kebanyakan orang. Menggunakan django-moneyseperti yang mereka soroti, termasuk penanganan mata uang . Jadi ini lebih untuk proyek yang melibatkan transaksi seperti situs e-commerce, gateway pembayaran, mata uang digital, perbankan, dll ....
Yeo
Saya berpendapat bahwa karena mereka bekerja dengan USD - mata uang - lebih masuk akal untuk menggunakan perpustakaan penanganan mata uang seperti django-money (python-money) karena membuat semuanya bekerja seperti yang Anda harapkan dan berikan penyesuaian fitur di masa mendatang. Pertanyaan asli mengatakan mereka membutuhkan pemformatan dan perhitungan (seperti yang Anda kutip) dan untuk itu Anda lebih baik menggunakan perpustakaan mata uang daripada bidang desimal sederhana.
Michael Thompson
1
Bagaimana jika saya ingin menambahkan dua bidang uang atau melakukan beberapa perhitungan?
saran3h
1
@ saran3h Anda dapat bekerja dengan contoh uang dan melakukan perhitungan seperti contoh angka (desimal) lainnya. Anda dapat menambah / mengurangi, mengalikan dengan bilangan bulat, dll.
Michael Thompson
9

Tentukan desimal dan kembalikan tanda $ di depan nilai.

    price = models.DecimalField(max_digits=8, decimal_places=2)

    @property
    def price_display(self):
        return "$%s" % self.price
Çagatay Melan
sumber
6
Anda menyadari bahwa Anda baru saja membuat loop rekursi tak terbatas di properti Anda, bukan?
El Ninja Trepador
Menarik. Bolehkah saya bertanya bagaimana itu?
kingraphaii
2
field = models.DecimalField(max_digits=8, decimal_places=2)

Harus membuat bidang untuk PostgreSQL seperti:

 "field" numeric(8, 2) NOT NULL

Yang merupakan cara terbaik untuk menyimpan jumlah dolar AS PostGreSQL.

Jika Anda membutuhkan field PostgreSQL jenis "presisi ganda", maka yang perlu Anda lakukan dalam model django:

field = models.FloatField()
herohat
sumber
3
Hati-hati dalam merepresentasikan uang sebagai angka floating point, karena orang cenderung tidak senang dengan kesalahan pembulatan pada uang mereka. Lihat: stackoverflow.com/questions/3730019/… untuk lebih jelasnya.
Adam Parkin