场景:我正在构建订单。与地球上的其他所有订单一样,它具有单独的发票送货地址。我刚刚添加了一个“使用帐单邮寄地址”复选框,让用户可以节省时间。
问题是,航运领域仍然存在。如果用户未输入任何送货地址数据(如果他们想使用帐单邮寄地址),他们将无法通过验证。
我认为我想要覆盖这些重复字段的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.
答案 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数据是不可变的。