Проблема при попытке повторно использовать идентификатор первичного ключа с помощью SQLAlchemy

1

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

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

  • PostgreSQL 8.4
  • Python 2.7
  • SQLAlchemy 0.7

У меня есть 3 таблицы: User, Inventories and Devices. У Inventory and Devices есть one- to- одно отношение с пользователем. User.id - это Inventories.user_id и Devices.user_id с внешней ключами.

У меня есть User, Devices и Inventories, настроенные в моделях/в соответствии со стандартными методами python.

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

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

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

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

>>>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()

В этот момент я либо получу eror, что Key (id) = (<id>) по-прежнему ссылается на таблицы "устройства" (или "запасы" ), где <id> является newUser.id до re- присваивая ему id 1

Я просмотрел каскадные и попробовал различные варианты (все, save- update и т.д.) без эффекта.

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

Спасибо,

Крыс

Теги:
sqlalchemy

3 ответа

0

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

0

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

Поскольку,

  • Вероятно, вы нарушите целостность данных, и это может вызвать серьезные проблемы.
  • Вам нужно будет разбить структуру приращения auto- идентификатора, поэтому до этого вам нужно назначить идентификатор вручную или использовать hand- написанный pre- save trigger, чтобы получить правильный идентификатор.
  • Если у вас есть таблицы с User foreginkey, которые устанавливают NOT null, возможно, у вас будет проблема с освобождением записей, связанных с удаленным пользователем. Если вы не обнуляете их, идентификатор re- будет создавать серьезную проблему целостности data- (неправильно связанные отношения)...

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

0

Чтобы устранить ошибку, которую вы видите, вы можете обновить внешние ключи всех моделей Device и Inventory, связанных с этой моделью User, прежде чем совершать. Вы должны убедиться, что ваша модель User не auto- увеличивает идентификатор (т.е. Не является последовательностью 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 (как во втором объявлении модели) и добавить другое поле в таблице пользователя, которое указывает, является ли пользователь администратором (для целей безопасности/тестирования, о которых вы упомянули). Таким образом, вам не нужно полагаться на магические числа в вашем приложении (например, идентификатор пользователя) для логики приложения, особенно безопасности.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню