Django 如果设置了布尔字段,则仅验证某些字段
场景:我正在生成订单。像地球上的其他订单一样,它有单独的发票发货地址。我刚刚添加了一个“使用账单地址”复选框,让用户节省时间 问题是,航运领域仍然存在。如果用户没有输入任何发货地址数据(例如,如果他们想使用账单地址),则验证将失败 我想我要做的是覆盖这些重复字段的ModelForm验证。在那里,如果复选框被选中(不确定如何从验证器中获取数据),我将返回计费版本。如果没有检查,我会将其传递回原始验证 听起来像个计划,不是吗?我在第一个跨栏时摔倒了。我的Django 如果设置了布尔字段,则仅验证某些字段,django,django-forms,django-validation,Django,Django Forms,Django Validation,场景:我正在生成订单。像地球上的其他订单一样,它有单独的发票发货地址。我刚刚添加了一个“使用账单地址”复选框,让用户节省时间 问题是,航运领域仍然存在。如果用户没有输入任何发货地址数据(例如,如果他们想使用账单地址),则验证将失败 我想我要做的是覆盖这些重复字段的ModelForm验证。在那里,如果复选框被选中(不确定如何从验证器中获取数据),我将返回计费版本。如果没有检查,我会将其传递回原始验证 听起来像个计划,不是吗?我在第一个跨栏时摔倒了。我的clean_函数不工作。看起来他们连电话都没有
clean_函数
不工作。看起来他们连电话都没有
下面是一些代码:
# 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.
我不确定我是否只是一个clutz,但以下方法奏效了(并回答了我的全部问题): 类订单(模型表单): 类元: 型号=订单
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()
但是如果你认为我走错了方向,请告诉我
正如Nick在下面指出的那样,已清理的\u数据不是在保证订单中填写的,这意味着当调用clean\u shipping\u street()
时,发货到\u账单可能不存在。解决方法是调用clean\u shipping\u street()
方法,而不是访问clean\u数据
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):
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()的调用要比我以前的工作少得多。但说真的,我怀疑你甚至不能在分析会话中检测到这些“改进”。我的上一个回答有几个问题。复制的数据没有返回到表单中(可能是您想要的,我需要),而且有点不可靠
这是我现在使用的。我没有添加几十个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数据是不可变的。这就是我要做的。可能不是最好的,但自定义清理方法可能是最简单的。请注意,clean\u
方法不会按任何特定顺序调用,因此在上述情况下,ship\u to\u billing
可能尚未在cleaned\u data
中设置。一般来说,如果您的clean方法依赖于表单中的多个项目,请使用普通的clean
方法。关于这一点,我有个主意。不是调用self.cleaned_data['field_name']
,而是调用self.clean_field_name()
——这样可以保证得到一个结果(除非自定义清理具有混乱的循环依赖关系)。对于CPU来说,这需要做更多的工作,但它应该一直工作。
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