PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, August 11, 2022

[FIXED] How to create mathematics operations with decimal in Django - [<class 'decimal.InvalidOperation'>]

 August 11, 2022     decimal, django, python     No comments   

Issue

A very simple save method causes this error :

class Shift(models.Model):
    branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    start_time = models.DateTimeField(auto_now_add=True)
    end_time = models.DateTimeField(null=True)
    closing_type_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    closing_actual_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    diff = models.DecimalField(max_digits=4, decimal_places=2, null=True)
    on_duty = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        self.diff = float(self.closing_type_amount) - float(self.closing_actual_amount)
        super(Shift, self).save(*args, **kwargs)

The cause of this error is the line self.diff = float(self.closing_type_amount) - float(self.closing_actual_amount) NOTE when give inputs more than 100 it fails ,, when a small numbers like 5, 4 , 6, 11 it works normally .


Solution

Because of the restrictions you have set. max_digits=4 and decimal_places=2 allows for a maximum number of 99.99 to be saved (decimal places are included in max digits).

See usage example here.

Since those are both required arguments you can set something high enough to work for most use cases. For example to store numbers up to approximately one billion with a resolution of 10 decimal places:

models.DecimalField(..., max_digits=19, decimal_places=10)

I would also suggest a bit of a change to your model because in my opinion saving the diff value is redundant since you already have the two values you calculate it from. Rather add a property to your model to calculate it on the fly:

class Shift(models.Model):
    branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    start_time = models.DateTimeField(auto_now_add=True)
    end_time = models.DateTimeField(null=True)
    closing_type_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    closing_actual_amount = models.DecimalField(max_digits=4, decimal_places=2, default=0)
    on_duty = models.BooleanField(default=True)

    @property
    def diff(self):
        return float(self.closing_type_amount) - float(self.closing_actual_amount)

Also, if you are going to cast to float you might as well use FloatField instead of DecimalField.



Answered By - Toni Sredanović
Answer Checked By - Gilberto Lyons (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing