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) 
Другие вопросы по тегам