Проблема при попытке повторно использовать идентификатор первичного ключа с помощью SQLAlchemy - PullRequest
1 голос
/ 28 мая 2011

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

В двух словах:

  • PostgreSQL 8,4
  • Python 2.7
  • SQLAlchemy 0.7

У меня есть 3 таблицы: Пользователь, Запасы и Устройства. Запасы и устройства имеют непосредственное отношение к пользователю. User.id имеет внешний ключ Inventories.user_id и Devices.user_id.

У меня есть Пользователь, Устройства и Инвентаризация, настроенные в моделях / в соответствии со стандартными практиками Python.

В интерактивном Python я могу без проблем выполнить следующие команды:

>>>newUser = User.create()
>>>newUser.device = User.create_device(<*args>)
>>>Session.add(newUser)
>>>Session.commit()

(учетная запись автоматически создается в коде)

Теперь, допустим, я хочу повторно использовать запись пользователя 1 (это единственная запись, которая разрешает метод, называемый сбросом в коде, из соображений безопасности и внутреннего тестирования)

>>>oldUser = User.retrieve(1)
>>>Session.delete(oldUser)
>>>Session.commit()

(подтвердить, что пользователь 1 больше не существует)

>>>newUser = User.create()
>>>newUser.device = User.create_device(<*args>)
>>>newUser.id = 1
>>>Session.add(newUser)
>>>Session.commit()

В этот момент я либо получу сообщение об ошибке, что Key (id) = (<id>) все еще ссылается из таблицы «устройства» (или «инвентаризации»), где <id> - это newUser.id перед повторным присвоение его идентификатору 1

Я изучил каскадирование и попробовал различные варианты (все, сохранить-обновить и т. Д.) Безрезультатно.

Любая информация, указывающая, где я иду не так, будет принята с благодарностью,

Спасибо

Крыс

Ответы [ 3 ]

0 голосов
/ 28 мая 2011

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

Потому что,

  • Возможно, вы нарушите целостность данных, и это может вызвать серьезные проблемы.
  • Вам потребуется нарушить структуру автоинкремента идентификатора, поэтому до тех пор вы должны назначать идентификаторы вручную или использовать рукописный триггер предварительного сохранения, чтобы получить правильный идентификатор.
  • Если у вас есть таблицы, которые имеют Пользовательский ключ пользователя , в котором значение NOT NULL, то у вас, вероятно, будут проблемы с освобождением записей, связанных с удаленным пользователем. Если вы не обнуляете их, повторно используемый идентификатор создаст серьезную проблему целостности данных (ошибочно ссылающиеся отношения) ...

Итак, прежде всего, вы должны решить, стоит ли это того?

0 голосов
/ 28 мая 2011

Так как это проблема, которая не должна быть замечена в производстве, просто используйте SET CONSTRAINTS. Вы можете использовать INITIALLY DEFERRED на своих FOREIGN KEY с, но я бы не рекомендовал этого, поскольку вы не имеете дело с циклической зависимостью, существующей в рабочей среде.

0 голосов
/ 28 мая 2011

Чтобы устранить ошибку, которую вы видите, вы можете обновить внешние ключи на всех моделях Device и Inventory, связанных с этой моделью User, перед фиксацией.Вам нужно убедиться, что ваша User модель не увеличивает автоматически идентификатор (то есть, это не последовательность PostgreSQL).

Например, объявление модели SQLAlchemy должно быть

class User(base):
    __tablename__ = 'user'
    id = Column('id', Integer, primary_key=True, unique=True, nullable=False)

вместо

class User(base):
    __tablename__ = 'user'
    id = Column('id', Integer, Sequence('user_id_seq'), primary_key=True)

НО, это, вероятно, неправильный способ сделать это!Лучше было бы использовать последовательность в User.id (как во втором объявлении модели) и добавить еще одно поле в пользовательскую таблицу, которое указывает, является ли пользователь администратором (для целей безопасности / тестирования, о которых вы упомянули).Таким образом, вам не нужно полагаться на магические числа в вашем приложении (например, идентификатор пользователя) для логики приложения, особенно для безопасности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...