web2py, unique = True не работает для ссылок на таблицы
Я просто пытаюсь создать простое приложение с 2 таблицами, связанными друг с другом в модели:
db.define_table('project',
Field('project_name','string',unique =True),
auth.signature)
db.define_table('watershed',
Field('project_name', requires = IS_IN_DB(db,db.project.project_name)),
Field('main_watershed','string', unique =True),
auth.signature)
db.watershed.main_watershed.requires = IS_NOT_EMPTY()
в контроллере:
def add_project():
form = SQLFORM(db.project).process()
if form.accepted: redirect('add_main')
return dict(form = form)
def add_main():
form = SQLFORM(db.watershed).process()
if form.accepted: redirect('add_main')
LIST = db(db.watershed).select()
return dict(form = form, LIST = LIST)
Предполагая, что пользователь вызывает default/add_project и добавляет "Project 1", если пользователь вызывает "default/add_project" и снова добавляет "Project 1", пользователь получает значение ошибки, которое уже существует в базе данных.
Если этот процесс перешел к default / add_main, если пользователь добавляет (например, в поле main_watershed = MAIN 1), появляется та же строка, в которой ошибка NO не появляется.
Чего-то не хватает? Почему моя ценность не уникальна?
1 ответ
unique=True
обеспечивается базой данных, а не процессом проверки формы. Если вы попытаетесь вставить значение, которое уже находится в базе данных, база данных должна вернуть ошибку, которая должна вызвать ошибку в вашем приложении web2py (но вы не получите красивое сообщение об ошибке, отображаемое в форме). Если вы хотите, чтобы проверка формы проверяла наличие дубликатов, вы должны использовать средство проверки IS_NOT_IN_DB:
Field('main_watershed', 'string',
requires=IS_NOT_IN_DB(db, 'watershed.main_watershed'))
Кроме того, вместо того, чтобы хранить дубликаты поля "имя_проекта" в таблице водоразделов, вы могли бы рассмотреть возможность сделать это ссылочным полем:
db.define_table('project',
Field('project_name', 'string',unique =True),
auth.signature,
format='%(project_name)s')
db.define_table('watershed',
Field('project', 'reference project'),
Field('main_watershed', 'string',
requires=IS_NOT_IN_DB(db, 'watershed.main_watershed')),
auth.signature)
Вы также должны использовать функцию URL() в вашем перенаправлении: redirect(URL('default', 'add_main'))
Наконец, чтобы упростить добавление водоразделов для недавно добавленного проекта, вы можете рассмотреть возможность передачи идентификатора проекта в функцию add_main и установить его в качестве значения по умолчанию для проекта:
def add_project():
form = SQLFORM(db.project).process()
if form.accepted:
redirect(URL('default', 'add_main', args=form.vars.id))
return dict(form = form)
def add_main():
project_id = request.args(0, cast=int, default=None)
db.watershed.project.default = project_id
form = SQLFORM(db.watershed).process()
if form.accepted:
redirect(URL('default', 'add_main', args=project_id)
LIST = db(db.watershed).select()
return dict(form = form, LIST = LIST)