Составной ключ в web2py

У меня есть таблица, определенная в web2py

db.define_table(
'pairing',
Field('user',writable=True,readable=True),
Field('uid', writable=True , readable=True)
)

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

2 ответа

Решение

Это зависит от того, что вы пытаетесь сделать. По умолчанию web2py автоматически создает автоинкремент id поле, чтобы служить первичным ключом для каждой таблицы, и это рекомендуемый подход, когда это возможно. Если вы имеете дело с устаревшей базой данных с составными первичными ключами и не можете изменить схему, вы можете указать primarykey атрибут, хотя и с некоторыми ограничениями (как описано здесь):

db.define_table('pairing', 
    Field('user', writable=True, readable=True), 
    Field('uid', writable=True, readable=True),
    primarykey=['user', 'uid'])

Возможно, вместо этого вам действительно не нужен настоящий составной первичный ключ, но вам просто нужен какой-то способ, чтобы гарантировать, что в таблицу будут вставлены только уникальные пары значений user / uid. В этом случае вы можете сделать это, указав правильно построенный IS_NOT_IN_DB валидатор для одного из двух полей:

db.define_table('pairing',
    Field('user', writable=True, readable=True),
    Field('uid', writable=True, readable=True))

db.pairing.uid.requires=IS_NOT_IN_DB(db(db.pairing.user==request.vars.user),
    'pairing.uid')

Это обязательно uid является уникальным среди множества записей, где user соответствует новому значению user вставляется (поэтому комбинация user а также uid Должно быть уникальным). Обратите внимание, валидаторы (такие как IS_NOT_IN_DB) применяются только тогда, когда значения вставляются через SQLFORM или используя .validate_and_insert() метод, поэтому вышеописанное не будет работать для произвольных вставок в таблицу, но в первую очередь предназначено для ввода данных пользователем.

Вы также можете использовать SQL для установки уникального ограничения на несколько столбцов для таблицы (что вы можете сделать непосредственно в базе данных или через web2py .executesql() метод). Однако даже с таким ограничением вы все равно захотите провести некоторую проверку входных данных в вашем приложении, чтобы избежать ошибок в базе данных.

Я использовал вычисляемое поле для создания / моделирования составного ключа. Взяв пример из приведенного выше вопроса, можно определить таблицу соединений следующим образом:

from md5 import md5
db.define_table( 'pairing',
                 Field('user', writable=True, readable=True),
                 Field('uid', writable=True, readable=True),
                 Field( 'user_uid_md5', 
                        length=32,
                        unique=True,
                        writable=False,
                        readable=False,
                        compute=lambda row: md5("{0}:{1}".format(row.user,row.uid)).hexdigest()))

user_uid_md5 поле автоматически вычисляется при вставке и обновлении. Значением этого поля является хеш md5 строки, полученной из двух полей user а также uid, Это поле также помечено как unique, Таким образом, база данных обеспечивает уникальность здесь, и это работает вокруг ограничения, указанного Энтони. Это также должно работать для эмуляции составных ключей с более чем двумя полями. Если вы видите какие-либо пробелы в этом подходе, пожалуйста, дайте мне знать.

Редактировать: Небольшое обновление способа вычисления хеша md5 с учетом случая, указанного Chen Levy в комментарии ниже.

Другие вопросы по тегам