Disclaimer: This field is kept for historical reason but since it converts the values to float, it is not suitable for true decimal storage. Consider using :class:`~mongoengine.fields.Decimal128Field`. Fixed-point decimal number field. Stores the value as a float by default unless `force_st
| 413 | |
| 414 | |
| 415 | class DecimalField(BaseField): |
| 416 | """Disclaimer: This field is kept for historical reason but since it converts the values to float, it |
| 417 | is not suitable for true decimal storage. Consider using :class:`~mongoengine.fields.Decimal128Field`. |
| 418 | |
| 419 | Fixed-point decimal number field. Stores the value as a float by default unless `force_string` is used. |
| 420 | If using floats, beware of Decimal to float conversion (potential precision loss) |
| 421 | """ |
| 422 | |
| 423 | def __init__( |
| 424 | self, |
| 425 | min_value=None, |
| 426 | max_value=None, |
| 427 | force_string=False, |
| 428 | precision=2, |
| 429 | rounding=decimal.ROUND_HALF_UP, |
| 430 | **kwargs, |
| 431 | ): |
| 432 | """ |
| 433 | :param min_value: (optional) A min value that will be applied during validation |
| 434 | :param max_value: (optional) A max value that will be applied during validation |
| 435 | :param force_string: Store the value as a string (instead of a float). |
| 436 | Be aware that this affects query sorting and operation like lte, gte (as string comparison is applied) |
| 437 | and some query operator won't work (e.g. inc, dec) |
| 438 | :param precision: Number of decimal places to store. |
| 439 | :param rounding: The rounding rule from the python decimal library: |
| 440 | |
| 441 | - decimal.ROUND_CEILING (towards Infinity) |
| 442 | - decimal.ROUND_DOWN (towards zero) |
| 443 | - decimal.ROUND_FLOOR (towards -Infinity) |
| 444 | - decimal.ROUND_HALF_DOWN (to nearest with ties going towards zero) |
| 445 | - decimal.ROUND_HALF_EVEN (to nearest with ties going to nearest even integer) |
| 446 | - decimal.ROUND_HALF_UP (to nearest with ties going away from zero) |
| 447 | - decimal.ROUND_UP (away from zero) |
| 448 | - decimal.ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero) |
| 449 | |
| 450 | Defaults to: ``decimal.ROUND_HALF_UP`` |
| 451 | :param kwargs: Keyword arguments passed into the parent :class:`~mongoengine.BaseField` |
| 452 | """ |
| 453 | self.min_value = min_value |
| 454 | self.max_value = max_value |
| 455 | self.force_string = force_string |
| 456 | |
| 457 | if precision < 0 or not isinstance(precision, int): |
| 458 | self.error("precision must be a positive integer") |
| 459 | |
| 460 | self.precision = precision |
| 461 | self.rounding = rounding |
| 462 | |
| 463 | super().__init__(**kwargs) |
| 464 | |
| 465 | def to_python(self, value): |
| 466 | # Convert to string for python 2.6 before casting to Decimal |
| 467 | try: |
| 468 | value = decimal.Decimal("%s" % value) |
| 469 | except (TypeError, ValueError, decimal.InvalidOperation): |
| 470 | return value |
| 471 | if self.precision > 0: |
| 472 | return value.quantize( |