1

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

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

我想我想要覆盖这些重复字段的 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.
4

2 回答 2

2

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

类 OrderForm(ModelForm): 类 Meta: 模型 = 订单

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()

但是,如果您认为我的做法是错误的,请告诉我!

正如尼克在下面指出的那样,cleaned_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() 的调用次数比我以前的努力少得多。但说真的,我怀疑你甚至可以在分析会话中检测到这些“改进”。

于 2009-11-27T22:35:14.887 回答
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 数据是不可变的。

于 2009-11-30T12:08:40.847 回答