#python #web2py #data-access-layer
#python #web2py #уровень доступа к данным
Вопрос:
Пожалуйста, рассмотрите следующую таблицу:
db.define_table('bio_data',
Field('name', 'string'),
Field('total_mark', 'integer', requires=IS_EMPTY_OR(IS_INT_IN_RANGE(0, 1e100))),
Field('marks_obtained', 'integer')
)
Теперь поле ‘marks_obtained’ не может иметь значение больше, чем ‘total_marks’.
Я попробовал следующее
db.bio_data.marks_obtained.requires = IS_EMPTY_OR(
IS_INT_IN_RANGE(0, db.bio_data.total_mark))
Но это не работает. Я получаю следующую ошибку:
TypeError: int() argument must be a string or a number, not 'Field'
Любая помощь приветствуется.
Комментарии:
1. найдите способ получить целочисленное значение
Field
.2. Да, это вопрос здесь, как я могу получить значение вместо поля. Я попробовал следующее, но все равно получаю ошибку:
Field('marks_obtained', 'integer', requires=lambda row: IS_EMPTY_OR(IS_INT_IN_RANGE(0, db.bio_data(row.id).total_mark)))
И прошу вас, пожалуйста, не снижать голос, не понимая всей проблемы или знаний.3. можете ли вы ввести
dir(db.bio_data.total_mark)
и посмотреть, что он возвращает? Вы только что пробовалиint(db.bio_data.total_mark)
4.
int(db.bio_data.total_mark)
это дает ту же ошибку, так как этот запросdb.bio_data.total_mark
возвращает поле вместо целого числа.
Ответ №1:
У меня была такая же проблема, и я только что нашел для нее элегантное решение. Во-первых, вы должны заметить, что перед любой проверкой значения полей передаются в модель, поэтому в модели вы можете манипулировать ими с помощью request.vars . После этого все остальное просто: просто создайте свой собственный валидатор, извлеките значения полей и используйте их по своему усмотрению. Пример будет лучше:
Предположим, у вас есть таблица с двумя полями:
dbOBJECT.define_table("example",
Field("high_number",
"integer",
label= T('High number'),
requires=[IS_NOT_EMPTY(T(stringBuilder.emptyField))]),
Field("other_number",
"integer",
label= T('Lower number'),
requires=IS_NOT_EMPTY(T(stringBuilder.emptyField))))
И вам нужно, чтобы второе число было меньше первого. Для объяснения давайте создадим пользовательский валидатор. Это можно сделать тем же db.py файл
class VALIDATE_NUMBERS(object):
def __init__(self, error_message="Error, this value can't be greather than the above one"):
self.error_message = error_message
def __call__(self, value):
error = None
high_number=request.vars['high_number']
if high_number < value:
error = self.error_message
return (value, error)
Ну, еще одна вещь, которую нужно сделать, это включить эту проверку в модель:
dbOBJECT.define_table("example",
Field("high_number",
"integer",
label= T('High number'),
requires=[IS_NOT_EMPTY(T(stringBuilder.emptyField))]),
Field("other_number",
"integer",
label= T('Lower number'),
requires=IS_NOT_EMPTY [(T(stringBuilder.emptyField)), VALIDATE_NUMBERS()]))
Волшебство сделано!!! Наслаждайтесь…
Ответ №2:
Вы можете легко сделать это с помощью onvalidation
функции обратного вызова. Прочитайте эту форму и валидаторы — onvalidation
Второе решение — вам нужно объединить «Валидаторы с зависимостями» и IS_EXPR
валидатор. Читать:
Добавьте валидатор в контроллер примерно следующим образом, я не тестировал это, но вы получите представление об этом.
is_total_less = int(request.vars.marks_obtained) < int(request.vars.total_mark)
db.bio_data.marks_obtained.requires = IS_EMPTY_OR(
IS_EXPR('%s' % is_total_less,
error_message='Marks Obtained should be smaller than Totak Marks'))
Убедитесь, что request.vars
оно доступно.
Комментарии:
1. Я смог сделать это с помощью
onvalidation
обратного вызова. Для уровня модели я попробую то же самое и обновлю. Спасибо за обновление.