Как сделать многоколоночные уникальные ограничения на уровне базы данных в web2py?

Если у меня есть что-то подобное в моем models/db.py:

   db.define_table('magazine', Field('name'), Field('description'))
   db.define_table('subscribe', Field('subscriber', db.auth_user), Field('magazine', db.magazine))

И в controller/default.py:

# subscribe callback from view
@auth.requires_login()
def subscribe():
    mag_id = request.args(0, cast=int)
    db.subscribe.insert(magazine=mag_id, subscriber=auth.user.id)

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

Как сделать так, чтобы таблица подписки содержала уникальные комбинации подписчика и журнала? Подписчик, который подписался на журнал, не должен иметь возможность снова подписаться на тот же журнал.

Например, это должно работать:

Пользователь 1, Магазин 1
Пользователь 1, Магазин 2
Пользователь 2, Магазин 1

Но это не должно:

Пользователь 1, Магазин 1
Пользователь 1, Магазин 1

Одним из решений была ручная проверка, существует ли комбинация внутри моего контроллера:

def subscribe():
    mag_id = request.args(0, cast=int)
    subscribed = db(db.subscribe.subscriber==auth.user.id)&(db.subscribe.magazine==mag_id))

    if len(subscribed) < 1:
        # Do insert
    else:
        # Do nothing, user is already subscribed.

Но есть ли лучший способ (желательно на уровне базы данных) сделать это? Я читал, что использование IS_NOT_IN_DB() может работать, но, похоже, оно ограничено использованием форм? эта тема также предполагает, что она не будет работать. .


person Bak    schedule 01.05.2013    source источник


Ответы (1)


DAL не предоставляет способа указать ограничение уникальности нескольких столбцов в базе данных, но вы можете сделать это непосредственно в базе данных вне web2py. Тем не менее, вы, вероятно, все еще хотите, чтобы какой-то явный код в приложении обрабатывал это, иначе нарушение на уровне базы данных просто приведет к созданию исключения. В этом случае вы можете просто использовать метод .update_or_insert():

db.subscribe.update_or_insert(magazine=mag_id, subscriber=auth.user.id)

Это сделает вставку только в том случае, если запись с этим журналом и подписчиком еще не существует.

person Anthony    schedule 01.05.2013
comment
О, это очень удобно. Спасибо, это, вероятно, поможет. - person Bak; 01.05.2013