Проверяйте только определенные поля, если установлен BooleanField - PullRequest
1 голос
/ 28 ноября 2009

Сценарий: я строю форму заказа. Как и любая другая форма заказа на планете, она имеет отдельные адреса доставки для выставления счетов. Я только что добавил флажок «Использовать платежный адрес», чтобы позволить пользователю сэкономить время.

Проблема в том, что поля доставки все еще там. Они не пройдут проверку, если пользователь не введет данные адреса доставки (например, если он хочет использовать платежный адрес).

То, что я хотел бы сделать, переопределяет проверку 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 ]

2 голосов
/ 28 ноября 2009

Я не уверен, был ли я просто тупиком, но следующее сработало (и отвечает на весь мой вопрос):

класс 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 () вызывается намного меньше, чем мои предыдущие попытки. А если серьезно, я сомневаюсь, что вы могли даже обнаружить эти «улучшения» в сеансе профилирования.

1 голос
/ 30 ноября 2009

Было несколько проблем с моим последним ответом. Скопированные данные не были возвращены обратно в форму (возможно, это то, что вы хотите), и это было немного ненадежно.

Вот что я сейчас использую. Вместо добавления десятков 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 неизменны.

...