Closed rafalp closed 6 years ago
Could we provide any useful validators? Some examples:
Merging #53 into master will increase coverage by
1.41%
. The diff coverage is95.12%
.
@@ Coverage Diff @@
## master #53 +/- ##
==========================================
+ Coverage 94.73% 96.15% +1.41%
==========================================
Files 3 4 +1
Lines 76 104 +28
Branches 5 10 +5
==========================================
+ Hits 72 100 +28
Misses 2 2
Partials 2 2
Impacted Files | Coverage Δ | |
---|---|---|
django_prices/templatetags/prices_i18n.py | 95.83% <100%> (-0.09%) |
:arrow_down: |
django_prices/templatetags/prices.py | 100% <100%> (ø) |
:arrow_up: |
django_prices/validators.py | 100% <100%> (ø) |
|
django_prices/widgets.py | 88.23% <71.42%> (-0.66%) |
:arrow_down: |
Continue to review full report at Codecov.
Legend - Click here to learn more
Δ = absolute <relative> (impact)
,ø = not affected
,? = missing data
Powered by Codecov. Last update 67bd17b...707aece. Read the comment docs.
Let's remove Django 2.0 from allowed failures, it's a stable release now.
I've added MinMoneyValidator
, MaxMoneyValidator
and MoneyPrecisionValidator
that check if money is at least, at most or precise enough. Each of those validators is just layer of abstraction above the Django's validator: MinValueValidator
, MaxValueValidator
and the DecimalValidator
.
Min/Max only change to original is that they display formatted money in error message instead of Money(123, 'USD')
and the MoneyPrecisionValidator
will raise if you've got number of sub-units for currency wrong, eg 100.999 EUR
. All of validators also throw with ValueErrors if you use them with different currencies, in spirit of the contract from prices
.
Following explicit better than implicit rule I've changed the MoneyPrecisionValidator
to rely on passed decimal_places
instead of resolving that on its own via asking babel how many decimal_places
to use. This validator now closely follows DecimalValidator that it extends, except it works with Money and currencies instead of Decimals.
Doesn't that mean that the common use case will require the user to call babel
manually?
I think a typical case would be to check that a value fits the minimum of:
decimal_places
(likely coming from the model and reflecting of what the underlying DB field can store)Doesn't that mean that the common use case will require the user to call
babel
manually?
Yeah. I've landed there after looking under the hood of Django's DecimalField
handling. Here, they have nice Model -> Field -> Validator, passing decimal_places at all times. In my code it was Model -> Field, and then validator just disregards what's passed from Field it and goes for its own from currency. This felt like breaking the pattern and I've redid it to play by same rules everywhere.
I think a typical case would be to check that a value fits the minimum of:
This is good idea. Picking from there I'm wondering if there would be any downsides if we've simply madedecimal_places
optional, only required when dealing with custom currency that babel
fails for, eg. like dogecoins, otherwise being resolved automatically from your currency's name. This could be done in our model and form fields as well as in the validator.
I think the problem with decimal_places
being optional is that it will be provided by Django by default. If that means ignoring the currency precision then I'm afraid in most common cases the currency will be ignored.
All-right. Validator raises if either of those two are true:
decimal_places
is specified and shorter than fractional, this is opt-in because decimal_places
is optional arg in DecimalValidator
that we are using behind the courtains. This is good in case of model forms as it will fail if we've forgot to increase the decimal_places
while setting up store for, eg. Kuwait dinar.currency
is recognized by babel.numbers.is_currency
and fractional is longer than get_currency_precision(currency)
, so writing MoneyPrecisionValidator('USD', 9, 3)
by mistake will still keep you safe because because thanks to babel we'll also test against decimal_places=2
. Finally MoneyPrecisionValidator('BTC', 15, 10)
also works if somebody has usecase for such, we just don't know what precision BTC allows and will roll with whatever was configured.Another pass: changed validation on model field to pass Money
to validators instead of Money.amount
and also create MoneyPrecisionValidator
for itself just like how DecimalField
creates DecimalValidator
for itself. I've also iterated on our tests suite a little.
This is work in progress PR that updates our lib to beta 3, thus making it work with latest changes in our
prices
library.TODO
decimal_places
handling