首页 > 解决方案 > Django:如何在两个FormFields之间验证/验证一个“更大的”?

问题描述

我正在 Django 中测试编写验证器。到目前为止它有效,但现在我想写一些类似“范围”的东西。

表格.py

class AnimalForm(forms.ModelForm):
    weight = forms.DecimalField(validators=[validate_gtr])

    class Meta:
        model = Animal
        fields = [
            'name',
            'weight',
            'daily_food_min',
            'daily_food_max',          
            'species',
            'farmer',    
        ]

    def __init__(self, *args, **kwargs):
        super(AnimalForm, self).__init__(*args, **kwargs)
        self.fields['name'].help_text = 'Name of Animal'
        self.fields['weight'].help_text = 'Weight in Kg'
        self.fields['species'].help_text = 'choose a species'

验证器.py

from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _



def validate_gtr(value):
    if value > 100:
        raise ValidationError(
            _('(value) Kg. Animal is too heavy'),
            params={'value': value},
        )

问题

正如你所看到的,我已经写了一个简单的验证validate_gtr来检查我的动物的重量——它奏效了。现在我想验证daily_food_mindaily_food_max相互对抗,这意味着在保存或在我的 html 表单中输入数字时,daily_food_max它必须更大。daily_food_min

这是我的方法

表格.py

class AnimalForm(forms.ModelForm):
    weight = forms.DecimalField(validators=[validate_gtr])
    daily_food_min = forms.IntegerField(min_value=0, validators=[validate_food])
    daily_food_max = forms.IntegerField(min_value=1, validators=[validate_food])
<...>

验证器.py

  <...>

def validate_food(daily_food_min, daily_food_max):
    if daily_food_min > daily_food_max:
        raise ValidationError(
            _('(daily_food_min) Kg. is higher then max.'),
            params={
                'daily_food_max': daily_food_max,
                'daily_food_min': daily_food_min,                  
                    },
        )

不幸的是,当我填写我的 html 表单时收到错误消息:

TypeError: validate_food() missing 1 required positional argument: 'daily_food_max'

如何将这两个值发送到我的验证或声明位置参数?

标签: djangodjango-modelsdjango-formsdjango-templates

解决方案


好的,感谢文档中的@Jordan M. 提示,我想出了这个对我有用的灵魂。

我写了一个clean()方法,这是我更新的表格。

表格.py

class AnimalForm(forms.ModelForm):
    weight = forms.DecimalField(validators=[validate_gtr])
    daily_food_min = forms.IntegerField(min_value=0)
    daily_food_max = forms.IntegerField(min_value=1)

    class Meta:
        model = Animal
        fields = [
            'name',
            'weight',
            'daily_food_min',
            'daily_food_max',          
            'species',
            'farmer',    
        ]

    def __init__(self, *args, **kwargs):
        super(AnimalForm, self).__init__(*args, **kwargs)
        self.fields['name'].help_text = 'Name of Animal'
        self.fields['weight'].help_text = 'Weight in Kg'
        self.fields['species'].help_text = 'choose a species'

    def clean(self):
            cleaned_data = super().clean()
            daily_food_min = cleaned_data.get("daily_food_min")
            daily_food_max = cleaned_data.get("daily_food_max")

            if daily_food_min and daily_food_max:
                # Only do something if both fields are valid so far.
                if daily_food_min > daily_food_max:
                    raise forms.ValidationError(
                        "Food min. has to be less then Food max."
                    )

推荐阅读