Целочисленное поле не увеличивается автоматически в SQLAlchemy

У меня есть модель Flask-SQLAlchemy с полем Integer, которое я хотел бы автоинкрементировать. Это не первичный ключ; это суррогатный идентификатор. Модель выглядит так:

class StreetSegment(db.Model):
    id = db.Column(db.Integer, autoincrement=True)
    seg_id = db.Column(db.Integer, primary_key=True)

Когда я создаю таблицу в своей базе данных Postgres, поле id создается как простое целое число. Если я вставляю строки без указания значения для id, он не заполняется. Есть ли способ заставить SQLAlchemy использовать SERIAL, даже если это не первичный ключ?


person Rob    schedule 09.03.2016    source источник


Ответы (2)


Используйте Sequence вместо autoincrement:

id = db.Column(db.Integer, db.Sequence("seq_street_segment_id"))
person univerio    schedule 10.03.2016
comment
Я добавил это в свою модель, но при миграции (с flask_migrate) никаких изменений не обнаружено. - person Rob; 11.03.2016
comment
@Jura Alembic не является полностью автоматическим решением. Вам нужно написать миграцию самостоятельно, если она не обнаруживается автоматически. - person univerio; 11.03.2016
comment
У меня это не работает. Даже после того, как я удалю БД и начну заново, она просто вводит пустое значение для id. - person ChickenFeet; 10.03.2017
comment
@ChickenFeet Вы уверены, что создаете последовательность при создании базы данных? Попытайтесь распечатать запросы, которые выдаёт SQLAlchemy, когда вы делаете create_all(). - person univerio; 10.03.2017
comment
Нет, я не уверен. Я использую автоматические db_create и db_migrate из блога: blog.miguelgrinberg.com/post/. В любом случае я решил отказаться от автоматического увеличения и просто вручную настраиваю его каждый раз, когда создаю новую запись. В любом случае спасибо за ваш ответ, я видел несколько ответов, похожих на ваши, поэтому я уверен, что вы порекомендовали правильное решение :) - person ChickenFeet; 10.03.2017

SQLAlchemy не поддерживает auto_increment для столбцов без первичного ключа.

Если ваша база данных поддерживает это, вы можете настроить такое же поведение, используя последовательности. PostgreSQL поддерживает это. На самом деле последовательности не привязаны к конкретному столбцу. Вместо этого они существуют на уровне базы данных и могут использоваться повторно. Последовательности - это точная конструкция, которую SQLAlchemy использует для автоматического увеличения столбцов первичного ключа.

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

Вы можете связать последовательность со столбцом в конструкторе столбца . Помогает DDL Expression Constructs API вы создаете и отбрасываете последовательность.

Пример:

from alembic import op
import sqlalchemy as sa

measurement_id_seq = sa.Sequence('Measurement_MeasurementId_seq') # represents the sequence


def upgrade():
  op.execute(sa.schema.CreateSequence(measurement_id_seq)) # create the sequence
  op.create_table(
      'Measurement',
      sa.Column('DataSourceId',
                sa.Integer,
                sa.ForeignKey('DataSource.DataSourceId'),
                nullable=False),
      sa.Column('LocationId',
                sa.Integer,
                sa.ForeignKey('Location.LocationId'),
                nullable=False),
      sa.Column('MeasurementId',
                sa.Integer,
                measurement_id_seq, # the sequence as SchemaItem
                server_default=measurement_id_seq.next_value())) # next value of the sequence as default
      [...]
  op.create_primary_key('Measurement_pkey', 'Measurement',
                        ['DataSourceId', 'LocationId', 'Timestamp'])
  pass


def downgrade():
  op.execute(
      sa.schema.DropSequence(sa.Sequence('Measurement_MeasurementId_seq')))
  op.drop_constraint('Measurement_pkey', 'Measurement')
  op.drop_table('Measurement')
  pass
person Alexander Eble    schedule 12.05.2021