Использование лямбды для модели по умолчанию в Web2py - PullRequest
3 голосов
/ 07 сентября 2011

Я пытаюсь использовать лямбду, чтобы установить значение по умолчанию на основе значения в другой таблице.

Вот моя модель:

db.define_table('trip_instance', timestamp, sos_table, 
    Field('trip_type_id',  db.trip_type, label='Trip Type', 
       widget=trip_select_widget, requires = IS_IN_DB(db, 'trip_type.id', '% 
       (name)s'), represent=lambda id:db.trip_type(id)['name']), 
    Field('total_slots', 'integer', default=lambda r: 
       db.trip_type(r.trip_type_id)['total_slots']), 

Локально это вызывает ошибку, которая говорит:

TypeError: <lambda>() takes exactly 1 argument (0 given) 

И на моем сервере (Linode) ошибки нет, но когдаЯ пытаюсь создать новый экземпляр поездки с помощью sqlform. Поле общего количества слотов предварительно заполнено следующим образом:

<function <lambda> at 0x7f27684b7140> 

Моя лямбда выглядит почти идентично той, которая отлично работает для представления в поле trip_type_id, кроме I 'м, используя таблицу вместо поля.Это то, что я делаю не так?

1 Ответ

3 голосов
/ 07 сентября 2011

Если вы используете вызываемый (например, лямбда) для поля по умолчанию, я не думаю, что он может принимать какие-либо аргументы. Значения по умолчанию используются для предварительного заполнения полей формы, поэтому они не должны зависеть от других значений полей в записи.

Альтернативой является использование вычисляемого поля (хотя по умолчанию они не отображаются в SQLFORM). Другой вариант - обработать присвоение на этапе обработки формы, возможно, с помощью функции подтверждения - что-то вроде этого:

form.accepts(...,onvalidation=lambda form:form.vars.update(
    total_slots=form.vars.total_slots or
    db.trip_type(form.vars.trip_type_id)['total_slots']))

В приведенном выше коде, если передано значение для total_slots, оно сохраняется - в противном случае значение по умолчанию извлекается из таблицы trip_type на основе значения переданного trip_type_id.

UPDATE:

Как отмечается в комментариях, если вы включите в форму поле total_slots, если поле будет оставлено пустым при отправке формы, в базе данных будет храниться пустое значение, а не вычисленное значение. Чтобы избежать этой проблемы, вы можете указать функцию проверки для формы, которая проверяет, является ли form.vars.total_slots пустым, и, если это так, удаляет form.vars.total_slots. В этом случае, поскольку total_slots не будут включены во вставку в БД, для заполнения значения будет вызвана функция вычисления.

Если вы хотите полностью избежать каких-либо действий на этапе обработки формы, можно использовать еще один вариант создания пользовательского валидатора для поля total_slots. Метод __init__ валидатора может принимать request.vars в качестве аргумента, поэтому отправленные значения для записи будут доступны валидатору при отправке формы. Когда вызывается валидатор (то есть метод __call__), он может проверить, является ли значение total_slots пустым, и если это так, он может заменить его значением, вычисленным через функцию вычисления поля. При такой настройке стандартная функция вычислений будет обрабатывать прямые вставки в БД, а валидатор будет обрабатывать вставки через формы.

Обратите внимание, что при использовании метода validator значение total_slots будет вычислено на основе значений в request.vars, которые являются значениями переданных переменных до проверки . В этом случае это не должно быть проблемой, но в более общем случае, если какой-либо из валидаторов полей включает преобразования, значения в request.vars не будут точно соответствовать значениям, в конечном итоге вставленным в запись БД.

...