Составной ключ в 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 в комментарии ниже.