仅在设置BooleanField时验证某些字段

时间:2009-11-27 21:58:07

标签: django django-forms django-validation

场景:我正在构建订单。与地球上的其他所有订单一样,它具有单独的发票送货地址。我刚刚添加了一个“使用帐单邮寄地址”复选框,让用户可以节省时间。

问题是,航运领域仍然存在。如果用户未输入任何送货地址数据(如果他们想使用帐单邮寄地址),他们将无法通过验证。

我认为我想要覆盖这些重复字段的ModelForm验证。在那里,如果选中该框(不确定我如何从验证器中获取该数据),我将返回结算版本。如果没有选中,我会将其传回原始验证。

听起来像计划不是吗?好吧,我跌到了第一关。我的clean_functions无效。看起来他们甚至没有被召唤。

以下是一些代码:

# shipping_street is a field in my Order Model

class OrderForm(ModelForm):
    class Meta:
        model = Order

    def clean_shipping_street(self):
        print "JUST GET ME SOME OUTPUT!!!"
        raise forms.ValidationError('RAWRAWR')

以下是我的测试方法:

def checkout(request):
    of = OrderForm()
    if request.method == "POST":
        of = OrderForm(request.POST)
        print 'Form valid:', of.is_valid()

    # ...
    # return my HttpResponse with 'of' in the context.

2 个答案:

答案 0 :(得分:2)

我不确定我是不是只是一个克隆人,但以下工作(并回答了我的整个问题):

class OrderForm(ModelForm):     类Meta:         model =订单

def clean_shipping_street(self):
    print 'VALIDATING!!! YEY!'
    if self.cleaned_data['ship_to_billing']:
        return self.clean_billing_street()
    return super(OrderForm, self).clean_shipping_street()

但如果您认为我的方式错误,请告诉我!

正如尼克在下面指出的那样,cleaning_data没有填写保证订单,这意味着调用ship_to_billing时可能不存在clean_shipping_street()。解决这个问题的方法是调用clean_shipping_street()方法,而不是访问cleaned_data

def clean_shipping_street(self):
    print 'VALIDATING!!! YEY!'
    if self.clean_ship_to_billing():
        return self.clean_billing_street()
    return super(OrderForm, self).clean_shipping_street()

如果您在编写代码时没有像我那样懒惰,您可能希望避免对布尔字段进行如此多的重复验证。这应该更快(假设默认字段没有运行,除非需要 - 我自己也不确定):

def clean_shipping_street(self):
    print 'VALIDATING!!! YEY!'
    if self.cleaned_data.get('ship_to_billing', self.clean_ship_to_billing):
        return self.clean_billing_street()
    return super(OrderForm, self).clean_shipping_street()

甚至比这更好:

def clean_shipping_street(self):
    if not self.cleaned_data.has_key['ship_to_billing']:
        self.cleaned_data['ship_to_billing'] = self.clean_ship_to_billing()
    if self.cleaned_data['ship_to_billing']:
        return self.clean_billing_street()
    return super(OrderForm, self).clean_shipping_street()

它只是略有不同,但它应该意味着clean_ship_to_billing()被调用比我以前的努力少得多。但严重的是,我怀疑你甚至可以在分析会话中发现这些“改进”。

答案 1 :(得分:1)

我的上一个答案有几个问题。复制的数据没有呈现回形式(可能是你想要的东西,我这样做)并且它有点不可靠。

这是我现在正在使用的内容。我没有添加几十个clean_field_name()定义,而只是在BooleanField

def clean_ship_to_billing(self):
    if self.cleaned_data.get('ship_to_billing', False):
        data = self.data.copy()
        for f in ['street', 'street_2', 'post_code', 'city', 'county', 'country', ]:
            data['shipping_%s' % f] = data['billing_%s' % f]
        self.data = data

如果选中,则会将原始数据复制到装运字段中,以便计费字段。重要的是,该字段位于模型(或表单)字段顺序中的装运字段之前。

我正在复制self.data,因为POST数据是不可变的。