Global decimal rounding options in Django

独自空忆成欢 提交于 2019-12-20 04:54:05

问题


Decimal numbers are by default rounded very unexpectedly, in order to make it work normally, it is needed to use ROUND_HALF_UP option.

>>> from decimal import *
>>> Decimal("2.5").quantize(Decimal(1))
Decimal('2')
>>> getcontext().rounding = ROUND_HALF_UP
>>> Decimal("2.5").quantize(Decimal(1))
Decimal('3')
>>> Decimal("2.4").quantize(Decimal(1))
Decimal('2')

My question is - where in the Django application I have to set rounding option, so that it would work globally in the project? By saying globally I mean templates (floatformat template tag), views, model decimal field and so on.


回答1:


Decimal doesn't have anything to do with Django, they are part of the standard python library. The getcontext function returns the context of the current thread, so if you're not doing anything funky, every request will be executed in one thread. That basically mean that setting the option in the settings.py file should be enough.




回答2:


Worked in 1.9.5 (based on comment from @ark):

In myapp/apps.py

from __future__ import unicode_literals
import decimal
from django.apps import AppConfig


class MyAppConfig(AppConfig):

    name = 'myapp'

    def ready(self):
        # Set precision
        decimal.getcontext().prec = 9
        decimal.getcontext().rounding = decimal.ROUND_HALF_DOWN

In settings.py

INSTALLED_APPS = list(INSTALLED_APPS)
INSTALLED_APPS.append('myapp.apps.MyAppConfig')



回答3:


Actually it doesn't work like Viktor suggested (although in django 1.5).

My solution is create and using a middleware like this:

# -*- coding: utf-8 -*-

import decimal
from django.conf import settings


class DecimalPrecisionMiddleware(object):
    def process_request(self, request):
        decimal_context = decimal.getcontext()
        decimal_context.prec = settings.DECIMAL_PRECISION # say: 4

and then in settings.py:

MIDDLEWARE_CLASSES = (
    'pathto.middleware.DecimalPrecisionMiddleware',
    # etc..
)



回答4:


For django project can work setting decimal.DefaultContext (py3, py2).

This context is most useful in multi-threaded environments.

This is my code from settings.py:

import decimal
# Set global decimal rounding to ROUND_HALF_UP (instead of ROUND_HALF_EVEN).
project_context = decimal.getcontext()
project_context.rounding = decimal.ROUND_HALF_UP
decimal.DefaultContext = project_context

Worked in 1.10. Based on my answer in this question.



来源:https://stackoverflow.com/questions/18087777/global-decimal-rounding-options-in-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!