I'm using django-money for all currency fields in an app I'm building. According to the documentation the default CURRENCY_DECIMAL_PLACES is 2, and I am explicitly calling it in my settings.py file as well. However, when I am checking a remaining balance on an order it is returning a Money object, but showing all the decimal places instead of just 2.
In [2]: order.remaining_balance
Out[2]: Money('0.002500000000', 'USD')
Is there a reason it isn't restricting it to only the 2 decimal places that I am wanting? In the templates it is only showing two decimal places, but in my views.py file or the shell it renders the full decimal places.
I've set the CURRENCY_DECIMAL_PLACES to 2, but I'm getting back more than 2 decimal places.
Related
I want to find the minimum number with given conditions(is writer and is under probation), the below code works if D contains numbers, but how do I do it if the number is a part of a string, like a fraction for example? Like how do I use this formula if numbers in D look like "1/8", "31/688", "21/33", etc?
=MINIFS(D3:D1007, A3:A1007, "Writer", C3:C1007, "Probation")
I already have another formula that I use that calculates a decimal value given the fraction, If the fraction is in cell D21 then it would look like this:
=left(D21,find("/",D21)-1)/(right(D21,len(D21)-find("/",D21)))
but how do I apply this kind of formula in a minif/maxif?
I have attached a picture to show what I mean, what I'm trying to do is to put a formula in the passed/total column of package stats(probation), and it will get the lowest passed/total value out of the ones with that package name and importance level. as you can see, the entire writer package's pass rate is 5/8 because the lowest pass rate out of the writer package 5/8 is the lowest pass rate out people with package=writers and importance = probation. But at the moment I have to enter the 5/8s manually, I want it to be able to get it automatically using the formula I'm trying to figure out above.
try:
=ARRAYFORMULA(MIN(IF((A3:A="writer")*(C3:C="probation"),
IFERROR(REGEXEXTRACT(D3:D, "\d+")/REGEXEXTRACT(D3:D, "/(\d+)"), D3:D), )))
or to return fraction:
=ARRAYFORMULA(VLOOKUP(MIN(IF((A3:A="writer")*(C3:C="probation"),
IFERROR(REGEXEXTRACT(D3:D, "\d+")/REGEXEXTRACT(D3:D, "/(\d+)"), D3:D), )),
{IF((A3:A="writer")*(C3:C="probation"),
IFERROR(REGEXEXTRACT(D3:D, "\d+")/REGEXEXTRACT(D3:D, "/(\d+)"), D3:D), ), D3:D}, 2, 0))
also make sure fractions are formatted as plain text not date
I am trying to create an IF statement formula in excel that converts minutes to days and hours depending on the amount. Then rounds the value to 1 or 2 decimal points and adds the descriptive text (days, hours, etc) to the end
I have tried the following which converts and adds text but does not round:
=IF(L15>=1440, CONVERT(L15,"min","day") & CONCATENATE(L15," days"),
IF(L15>=60, CONVERT(L15,"min","hr") & CONCATENATE(L15," hours"),
IF(L15<=59, CONVERT(L15,"min","min") & CONCATENATE(L15," mins"))))
I would adjust your formula as follows and based on you wanting to round the final number
=IF(L15>=1440,ROUND(L15/1440,2)&" days",IF(L15>=60,ROUND(L15/60,2)&" hours",ROUND(L15,2)&" minutes"))
the ,2 in the ROUND function tell excel how many decimal places to calculate to. if format is set to general, trailing 0s will not be displayed. If you only want 1 decimal calculation then change the ,2 to ,1.
I have a DecimalField in my form and i would like to restrict min_value=0.1 and max_value=99.99
purity_percent = forms.DecimalField(max_value=99.99, min_value=0.1, decimal_places=2)
But when i try to enter value equal to 0.1 or 99.99 i will not work i get these error
For 0.1 : Ensure this value is greater than or equal to 0.1.
For 99.99 : Ensure this value is less than or equal to 99.99.
How to do i include those in the limit too.?
Floats, like 99.99, are stored in binary. Many numbers that can be represented with finite decimal digits are repeating fractions in binary (see many other questions for that).
In particular, the literal 99.99 is closer to:
>>> "{:.15f}".format(99.99)
'99.989999999999995'
Python also has Decimals:
>>> from decimal import Decimal
>>> d = Decimal("99.99")
And sure enough, the Decimal 99.99 is larger than the float max_value 99.99:
>>> d <= 99.99
False
The Django developers knew about binary and this is the entire reason for the existence of the DecimalField: it stores Decimals.
Conclusion: Use Decimal("99.99") as your max_value, not a float.
I am going through the beginning django ecommerce application for shopping cart app. I am getting the error as mentioned above while clicking the add to cart button.
I am getting the error at the line {{ cart_sutotal|currency}}
I remember that book... you're making a custom template filter right? You need to convert the value being passed in to locale.currency from a string to an int/decimal/float.
Best practice to avoid rounding errors with currency is to use the decimal package.
Import the decimal package and pass your value through the Decimal function to fix the issue.
from decimal import Decimal
value = Decimal(value)
So your code should look like this:
from django import template
import locale
from decimal import Decimal
register = template.Library()
#register.filter(name='currency')
def currency(value):
try:
locale.setlocale(locale.LC_ALL,'en_US.UTF-8')
except:
locale.setlocale(locale.LC_ALL,'')
value = Decimal(value)
loc = locale.localeconv()
return locale.currency(value, loc['currency_symbol'], grouping=True)
From the python docs.
abs()
Return the absolute value of a number. The argument may be a plain or long integer or a floating point number. If the argument is a complex number, its magnitude is returned.
The error raised suggest you are passing a str argument to the abs() method where as it expects the choice of above mentioned arguments. Solution would be to explicitly pass an integer object to the abs method.
Example:
>>>number = "1"
>>>print abs(int(number))
1
>>>
The currency filter expects its argument to be a numeric value; you're passing a string to your template as cart_sutotal.
Before passing it to the template, convert it to a decimal.Decimal, or, better, figure out why you're adding up price values and coming up with a string for the subtotal.
You are missing a cast somewhere in your code.
Wherever in the code you're doing abs(somevar) you need to cast a string to an integer by doing abs(int(somevar)). More info if you post a stacktrace or pieces of code.
I think your are writing the code from "beginning Django E-commerce" book.
The error is in your code you write {{ cart_sutotal|currency }} in place of {{ cart_subtotal }} .
bad operand type for abs(): 'str'
I solved this and wanted to share what I found.
Possible Cause: Decimal Field (or any number field) with "NaN"
In my case, I ended up with "NaN" trying to come into a Decimal form field, and that made the template processor choke with this exception in django/utils/numberformat.py. I had to figure out where I was saving "NaN" to the database.
I have a FloatField which can have values like 22.33405, 33.567 etc. Now, I need to query using only upto 2 places after decimal like below
#find all objects with value equal to 22.33
ModelName.objects.filter(field = 22.33)
Is it possible to do so - can I round off or just take first 2 places after decimal?
thanks
try this
ModelName.objects.filter(field__gte=22.33, field__lt=(22.33 + 0.01))
or
ModelName.objects.filter(field__range=(22.33, 22.33 + 0.01))
range lookup
Not directly. If you need this level of accuracy then you should be using DecimalField.