如何对Django Money进行向上取整?官方文档未找到相关方法
I get it, Django Money's Money class can be a bit tricky when it comes to rounding since it doesn't have a built-in __round__ method—hence that error you're seeing when trying to call round() directly on the object. And yeah, the official docs don't explicitly cover this, so let's break down how to handle it.
The Core Idea
Since Money wraps both an amount and a currency, you need to first extract the numeric value, perform your rounding operation on that, then wrap it back into a Money object. For rounding up, we'll use Python's math.ceil() function.
Basic Example: Round Up to Integer
Let's start with your original example where you want to round 99.21 SGD up to 100 SGD:
import math from djmoney.models.fields import Money # Your initial Money object xxx = Money(amount=99.21, currency='SGD') # Extract the numeric amount, round up, then rebuild the Money object rounded_amount = math.ceil(xxx.amount) rounded_money = Money(amount=rounded_amount, currency=xxx.currency) print(rounded_money) # Output: SGD 100.00
Round Up to Specific Decimal Places
If you need to round up to a certain number of decimal places (e.g., 99.215 SGD up to 99.22 SGD), adjust the calculation by multiplying and dividing by a power of 10:
import math from djmoney.models.fields import Money xxx = Money(amount=99.215, currency='SGD') # Round up to 2 decimal places decimals = 2 multiplier = 10 ** decimals rounded_amount = math.ceil(xxx.amount * multiplier) / multiplier rounded_money = Money(amount=rounded_amount, currency=xxx.currency) print(rounded_money) # Output: SGD 99.22
Reusable Helper Function
To make this easier to use across your codebase, wrap it in a helper function:
import math from djmoney.models.fields import Money def ceil_money(money_obj, decimals=0): """Round up a Money object to the specified number of decimal places.""" if not isinstance(money_obj, Money): raise TypeError("Input must be a Django Money object") multiplier = 10 ** decimals rounded_amount = math.ceil(money_obj.amount * multiplier) / multiplier return Money(amount=rounded_amount, currency=money_obj.currency) # Usage examples xxx = Money(amount=99.21, currency='SGD') yyy = Money(amount=99.211, currency='SGD') print(ceil_money(xxx)) # SGD 100.00 print(ceil_money(yyy, decimals=2)) # SGD 99.22
This approach works because we're directly operating on the underlying numeric value stored in the amount attribute of the Money object, then repackaging it with the original currency.
内容的提问来源于stack exchange,提问作者Wreeecks

