仅当设置了 BooleanField 时才验证某些字段
场景:我正在构建一个订单。与地球上所有其他订单一样,它有单独的发票送货地址。我刚刚添加了“使用帐单地址”复选框,以让用户节省时间。
问题是,运输场仍然存在。如果用户不输入任何送货地址数据(例如他们想使用帐单地址),他们将无法通过验证。
我想我想要覆盖这些重复字段的 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.
Scenario: I'm building an order-form. Like every other order-form on the planet, it has separate invoicing shipping addresses. I've just added a "Use billing address" checkbox to let the user save time.
The problem is, the shipping fields are still there. They will fail validation if the user don't enter any shipping address data (like if they want to use the billing address).
What I think I'd like to do override the ModelForm validation for these duplicate fields. In there, if the box is checked (not sure how I get that data from within a validator), I return the billing version. If it's not checked, I pass it back to the original validation.
Sounds like a plan doesn't it? Well I fell at the first hurdle. My clean_functions
aren't working. Doesn't look like they're even being called.
Here's some code:
# 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')
Here's how I'm testing:
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不确定我是否只是一个笨蛋,但以下方法有效(并回答了我的整个问题):
class OrderForm(ModelForm):
类元:
model = Order
但如果您认为我的做法是错误的,请告诉我!
正如 Nick 在下面指出的,cleaned_data 未按保证顺序填充,这意味着在调用
clean_shipping_street()
时,ship_to_billing
可能不存在。解决此问题的方法是调用clean_shipping_street()
方法,而不是访问cleaned_data
。如果您不像我编写代码时那么懒,您可能希望避免对布尔字段进行如此多的重复验证。这应该会更快(假设除非需要,否则默认字段不会运行 - 我自己不确定):
OR甚至比这更好:
这只是略有不同,但这应该意味着 clean_ship_to_billing() 被调用的次数比我之前的努力要少得多。但说真的,我怀疑您甚至可以在分析会话中检测到这些“改进”。
I'm not sure if I was just being a clutz but the following worked (and answers my whole question):
class OrderForm(ModelForm):
class Meta:
model = Order
But if you think I'm going about this the wrong way, please let me know!
As Nick points out below, cleaned_data isn't filled in a guaranteed order, meaning
ship_to_billing
might not exist whenclean_shipping_street()
is called. The way around this is to call theclean_shipping_street()
method instead accessingcleaned_data
.If you weren't as lazy as I was when I wrote the code, you might want to avoid so many duplicate validations of the boolean field. This should be faster (provided the default field isn't run unless it's needed - not sure on that myself):
OR even better than that:
It's only slightly different but it should mean clean_ship_to_billing() gets called a lot less than my previous efforts. But seriously, I doubt you could even detect these "improvements" in a profiling session.
我上次的回答有几个问题。复制的数据没有呈现回表单中(可能是您想要的,我就是这样做的)并且它有点不可靠。
这是我现在正在使用的。我没有添加数十个
clean_field_name()
定义,而是仅在BooleanField
上添加一个定义:如果选中,它会将账单字段的原始数据复制到发货字段中。重要的是,该字段位于模型(或表单)字段顺序中的发货字段之前。
我正在复制 self.data 因为 POST 数据是不可变的。
There were several problems with my last answer. Copied data wasn't rendered back into the form (might be something you want, I do) and it was a little unreliable.
Here is what I'm using now. Instead of adding dozens of
clean_field_name()
definitions, I have one just on theBooleanField
:If checked, it copies the raw data across for billing fields into shipping fields. It's important that the field is before the shipping fields in the model's (or form's) field order.
And I'm copying self.data because the POST data is immutable.