我想在调用ModelForm中的save()函数之前根据max_digits和decimal_places属性自动舍入Django的DecimalField。

当前使用以下内容:

  • django 1.8
  • python 2.7

  • 到目前为止我尝试过的。

    https://djangosnippets.org/snippets/10554/

    models.py
    amount = models.DecimalField(max_digits = 19, decimal_places = 2)
    

    views.py

    P.S.将其应用于不同的领域和不同的模型
    data = {"amount" : 100.1234,"name":"John Doe",...}
    form = My_form(data)
    if form.is_valid(): //the error throws from here.
        form.save()
    else:
        raise ValueError(form.errors)
    

    forms.py

    我计划清理clean()函数中的字段,并对所有十进制字段进行四舍五入,但是当我尝试打印raw_data时,没有“金额字段”。
    class My_form(forms.ModelForm):
        Class Meta:
            model = My_model
            fields = ('amount','name')
        def clean(self):
            raw_data = self.cleaned_data
            print(raw_data) //only prints {'name' : 'John Doe'}
    

    最佳答案

    您主要会收到此错误,因为forms.DecimalField具有与models.DecimalField分开的验证器:

    data = {'amount': 1.12345 }
    
    class NormalForm(forms.Form):
        amount = forms.DecimalField(max_digits = 19, decimal_places = 2)
    
    normal_form = NormalForm(data)
    normal_form.is_valid()  # returns False
    normal_form.cleaned_data  # returns {}
    

    默认情况下,forms.DecimalField用于具有models.DecimalField类字段的模型的表单。您可以执行以下操作:
    from django import forms
    from django.db import models
    from decimal import Decimal
    
    def round_decimal(value, places):
        if value is not None:
            # see https://docs.python.org/2/library/decimal.html#decimal.Decimal.quantize for options
            return value.quantize(Decimal(10) ** -places)
        return value
    
    class RoundingDecimalFormField(forms.DecimalField):
        def to_python(self, value):
            value = super(RoundingDecimalFormField, self).to_python(value)
            return round_decimal(value, self.decimal_places)
    
    class RoundingDecimalModelField(models.DecimalField):
        def to_python(self, value):
            # you could actually skip implementing this
            value = super(RoundingDecimalModelField, self).to_python(value)
            return round_decimal(value, self.decimal_places)
    
        def formfield(self, **kwargs):
            defaults = { 'form_class': RoundingDecimalFormField }
            defaults.update(kwargs)
            return super(RoundingDecimalModelField, self).formfield(**kwargs)
    

    现在,无论您在使用models.DecimalField的任何地方,都可以使用RoundingDecimalModelField代替。现在,与这些模型一起使用的任何表单都将使用自定义表单字段。
    class RoundingForm(forms.Form):
        amount = RoundingDecimalFormField(max_digits = 19, decimal_places = 2)
    
    data = {'amount': 1.12345 }
    
    rounding_form = RoundingForm(data)
    rounding_form.is_valid()  # returns True
    rounding_form.cleaned_data  # returns {'amount': Decimal('1.12')}
    

    关于python - 在调用save()之前,根据max_digits和decimal_places属性自动舍入Django的DecimalField。,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37958130/

    10-14 18:10