InvalidOperation: Invalid literal for Decimal: u' ' - django

When the users perform allocation of money in each envelope sometimes they forgot to put amounts in other envelopes which result to '0'. Then it will result to InvalidOperation.
How to fix this error? Or How can the system get only the amount that is more than 0?
Exception
Types: InvalidOperation
Value: Invalid literal for Decimal: u''
envelopes/views.py in allocate (application)
t2_payee = 'Envelope Transfer'
for val in request.POST:
if val[0:4] == "env_":
env = Envelope.objects.get(pk=int(val[4:]))
amt = Decimal(request.POST[val])
<WSGIRequest
path:/envelopes/allocate/6313/,
GET:<QueryDict: {}>,
POST:<QueryDict: {u'allocation_date': [u'2013-03-03'], u'month': [u'03'],
u'source': [u'6313'], u'year': [u'2013'], u'env_6316': [u''],
u'csrfmiddlewaretoken': [u'3kKoVymvIpbyhCknE1c3WH6YFznTaEoj'],
u'env_6315': [u'1'], u'env_6314': [u'0']}>,
COOKIES:{'__utma': '136509540.132217190.1357543480.1362303551.1362307904.34',
'__utmb': '1

In your example value of env_6316 is empty, Decimal doesn't know how to convert that to a number. You should check if the val is empty and if so then replace it with 0 before converting to Decimal.

I encountered this error while running a SQL query and attempting to construct a Pandas dataframe with the data returned from the query. An alteration to the query solved the problem for me. I had also attempted to CAST the column values returned, but ultimately, appending ::FLOAT8 to the problematic field was the only solution for me.
Example query:
SELECT sum(dollars)::FLOAT8 FROM [table] WHERE ...
sum(dollars) was the field causing the issue for me. It's Type in my table was numeric(10,6), and Size was 8.

Related

Unable to cast redshift column to integer due to empty values

I have a redshift table with a column which has empty values rarely. It is expected to have only integer values but some places empty values exist. When I try to cast it using :: it throws error -
[Code: 500310, SQL State: XX000] [Amazon](500310) Invalid operation: Invalid digit, Value 'B', Pos 0, Type: Integer
Details:
-----------------------------------------------
error: Invalid digit, Value 'B', Pos 0, Type: Integer
code: 1207
context: BEVEL_ON
query: 34112149
location: :0
process: query1_836_34112149 [pid=0]
-----------------------------------------------;
So to clarify you have a text column that contains numeric characters most of the time and you want to case this to integer, right? It also sounds like you believe that the only only non-numeric values are the empty string ''.
If this is the case then the solution is fairly simple - change the empty string to NULL before casting. The DECODE statement is my go to for this:
DECODE(col_X, '', NULL, col_X)::INT
If a more varied set of strings are in the column then using regexp_replace() to strip all the non-numeric characters would be needed.
text_to_int_alt(
case
when regexp_replace(convert(varchar, creative_id), '[^0-9]', '') <> '' then
regexp_replace(convert(varchar, creative_id), '[^0-9]', '')
end)

store infinity in postgres json via django

I have a list of tuples like below -
[(float.inf, 1.0), (270, 0.9002), (0, 0.0)]
I am looking for a simple serializer/deserializer that helps me store this tuple in a jsonb field in PostgreSQL.
I tried using JSONEncoder().encode(a_math_function) but didn't help.
I am facing the following error while attempting to store the above list in jsonb field -
django.db.utils.DataError: invalid input syntax for type json
LINE 1: ...", "a_math_function", "last_updated") VALUES (1, '[[Infinit...
DETAIL: Token "Infinity" is invalid.
Note: the field a_math_function is of type JSONField()
t=# select 'Infinity'::float;
float8
----------
Infinity
(1 row)
because
https://www.postgresql.org/docs/current/static/datatype-numeric.html#DATATYPE-FLOAT
In addition to ordinary numeric values, the floating-point types have
several special values:
Infinity
-Infinity
NaN
yet, the json does not have such possible value (unless its string)
https://www.json.org/
value
string
number
object
array
true
false
null
thus:
t=# select '{"k":Infinity}'::json;
ERROR: invalid input syntax for type json
LINE 1: select '{"k":Infinity}'::json;
^
DETAIL: Token "Infinity" is invalid.
CONTEXT: JSON data, line 1: {"k":Infinity...
Time: 19.059 ms
so it's not the jango or postgres limitation - just Infinity is invalid token, yet 'Infinity' is a valid string. so
t=# select '{"k":"Infinity"}'::json;
json
------------------
{"k":"Infinity"}
(1 row)
works... But Infinity here is "just a word". Of course you can save it as a string, not as numeric value and check every string if it's not equal "Infinity", and if it is - launch your program logic to treat it as real Infinity... But in short - you can't do it, because json specification does not support it... same asyou can't store lets say red #ff0000 as colour in json - only as string, to be caught and processed by your engine...
update:
postgres would cast float to text itself on to_json:
t=# select to_json(sub) from (select 'Infinity'::float) sub;
to_json
-----------------------
{"float8":"Infinity"}
(1 row)
update
https://www.postgresql.org/docs/current/static/datatype-json.html
When converting textual JSON input into jsonb, the primitive types
described by RFC 7159 are effectively mapped onto native PostgreSQL
types
...
number numeric NaN and infinity values are disallowed

Randomly set one-third of na's in a column to one value and the rest to another value

I'm trying to impute missing values in a dataframe df. I have a column A with 300 NaN's. I want to randomly set 2/3rd of it to value1 and the rest to value2.
Please help.
EDIT: I'm actually trying to this on dask, which does not support item assignment. This is what I have currently. Initially, I thought I'll try to convert all NA's to value1
da.where(df.A.isnull() == True, 'value1', df.A)
I got the following error:
ValueError: need more than 0 values to unpack
As the comment suggests, you can solve this with Series.where.
The following will work, but I cannot promise how efficient this is. (I suspect it may be better to produce a whole column of replacements at once with numpy.choice.)
df['A'] = d['A'].where(~d['A'].isnull(),
lambda df: df.map(
lambda x: random.choice(['value1', 'value1', x])))
explanation: if the value is not null (NaN), certainly keep the original. Where it is null, replace with the corresonding values of the dataframe produced by the first lambda. This maps values of the dataframe (chunks) to randomly choose the original value for 1/3 and 'value1' for others.
Note that, depending on your data, this likely has changed the data type of the column.

Django - coercing to Unicode

I am having a unicode problem and, as everytime I have something related I'm completely lost..
One of my Django template renders a TypeError :
Exception Value:
coercing to Unicode: need string or buffer, long found
The line giving trouble is just a string ( which I want to use in a mysql query) :
query = unicode('''(SELECT asset_name, asset_description, asset_id, etat_id, etat_name FROM Asset LEFT OUTER JOIN Etat ON etat_id_asset=asset_id WHERE asset_id_proj='''+proj+''' AND asset_id_type='''+t.type_id+''' ORDER BY asset_name, asset_description) UNION (SELECT asset_name, asset_description, asset_id, 'NULL', 'NULL' FROM Asset WHERE asset_id_proj='''+proj+''' AND asset_id_type='''+t.type_id+''' AND asset_id IN (SELECT etat_id_asset FROM Etat)); ''')
What can be wrong here ?
I know you figured out a better way to accomplish, but to answer the original question, in case you get that error again somewhere else in the project:
t.type_id appears to be a long integer. You cannot mix integers in strings unless you convert to string, this is really simple:
myString = 'some string with type id ' + str(t.type_id) + ', and whatever else you want in the string.'

Errors in Decimal Calcs within def clean method?

I'm attempting a few simple calculations in a def clean method following validation (basically spitting out a euro conversion of retrieved uk product price on the fly). I keep getting a TypeError.
Full error reads:
Cannot convert {'product': , 'invoice': , 'order_discount': Decimal("0.00"), 'order_price': {...}, 'order_adjust': None, 'order_value': None, 'DELETE': False, 'id': 92, 'quantity': 8} to Decimal
so I guess django is passing through the entire cleaned_data form to Decimal method. Not sure where I'm going wrong - the code I'm working with is:
def clean_order_price(self):
cleaned_data = self.cleaned_data
data = self.data
order_price = cleaned_data.get("order_price")
if not order_price:
try:
existing_price = ProductCostPrice.objects.get(supplier=data['supplier'], product_id=cleaned_data['product'], is_latest=True)
except ProductCostPrice.DoesNotExist:
existing_price = None
if not existing_price:
raise forms.ValidationError('No match found, please enter new price')
else:
if data['invoice_type'] == 1:
return existing_price.cost_price_gross
elif data['invoice_type'] == 2:
exchange = EuroExchangeRate.objects.latest('exchange_date')
calc = exchange.exchange_rate * float(existing_price.cost_price_gross)
calc = Decimal(str(calc))
return calc
return cleaned_data
If the invoice is of type 2 (a euro invoice) then the system should grab the latest exchange rate and apply that to the matching UK pound price pulled through to get euro result.
Should performing a decimal conversion be a problem within def clean method?
Thanks
I'm going to assume you've made an indentation error on pasting, and the lines from if data['invoice_type'] == 1: should actually be indented one level back - otherwise, as Alex says, the code will never get to the Decimal conversion.
There are multiple other problems with this code, but the biggest is that the last line returns the whole cleaned_data dictionary, rather than the value of this particular field - I suspect this is the cause of the error you are seeing.
Other than that, there is a big error where you calculate calc by multiplying cost_price_gross by exchange. Here exchange is an instance of EuroExchangeRate, rather than a number, so this calculation will not work.