Flask-sqlalchemy创建多列独立列的多列独立列

发布于 2025-02-13 12:16:00 字数 1412 浏览 0 评论 0原文

我在烧瓶项目中有一个模型:

class Location(db.Model):
    __tablename__ = 'location'

    id = db.Column(db.Integer, primary_key=True)
    longitude = db.Column(db.Float, nullable=False)
    latitude = db.Column(db.Float, nullable=False)
    address_1 = db.Column(db.String(50))
    address_2 = db.Column(db.String(8))
    country_id = db.Column(db.Integer, db.ForeignKey('country.id', ondelete='SET NULL'))
    city_id = db.Column(db.Integer, db.ForeignKey('city.id', ondelete='SET NULL'))

我需要通过对除ID以外的所有列应用唯一约束来确保位置的唯一性。我已经尝试了这个:

__table_args__ = (
        db.UniqueConstraint(
            longitude,
            latitude,
            address_1,
            address_2,
            country_id,
            city_id,
            name="unique_loc"),
    )

...但是,由于可取消的addresp_1','adversion_2'(在更多详细信息中)。我已经进行了一些调查,发现可能解决方案

CREATE UNIQUE INDEX unique_loc ON location
(longitude, latitude, COALESCE(address_1, ''), COALESCE(address_2, ''), country_id, city_id);

是否可以通过ORM或RAW查询编写此约束?我使用的数据库 - Postgres 13。任何帮助将不胜感激。

I have a model in my flask project:

class Location(db.Model):
    __tablename__ = 'location'

    id = db.Column(db.Integer, primary_key=True)
    longitude = db.Column(db.Float, nullable=False)
    latitude = db.Column(db.Float, nullable=False)
    address_1 = db.Column(db.String(50))
    address_2 = db.Column(db.String(8))
    country_id = db.Column(db.Integer, db.ForeignKey('country.id', ondelete='SET NULL'))
    city_id = db.Column(db.Integer, db.ForeignKey('city.id', ondelete='SET NULL'))

I need to ensure uniqueness of location via applying unique constraint on all columns except an id. I've tried this one:

__table_args__ = (
        db.UniqueConstraint(
            longitude,
            latitude,
            address_1,
            address_2,
            country_id,
            city_id,
            name="unique_loc"),
    )

... but I still can save duplicates because of nullable `address_1', 'address_2' (in more details). I've investigated a bit and found a possible solution:

CREATE UNIQUE INDEX unique_loc ON location
(longitude, latitude, COALESCE(address_1, ''), COALESCE(address_2, ''), country_id, city_id);

Is it possible to write this constraint either via ORM or raw query? The database I use - postgres 13. Any help would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

赤濁 2025-02-20 12:16:00

您可以使用index(带有unique = true选项)和func.coalesce

   from sqlalchemy import func
   ...   

   __table_args__ = (
        db.Index(
            "unique_loc",
            longitude,
            latitude,
            func.coalesce(address_1, ''),
            func.coalesce(address_2, ''),
            country_id,
            city_id,
            unique=True
        ),
    )

You can use Index (with unique=True option) and func.coalesce:

   from sqlalchemy import func
   ...   

   __table_args__ = (
        db.Index(
            "unique_loc",
            longitude,
            latitude,
            func.coalesce(address_1, ''),
            func.coalesce(address_2, ''),
            country_id,
            city_id,
            unique=True
        ),
    )
另类 2025-02-20 12:16:00

因此,我发现了如何使用RAW查询创建索引。您所需要的只是用flask db迁移生成新的迁移,并修改def升级()和'def defalgrade“:

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    ...
    op.execute(f"CREATE UNIQUE INDEX unique_loc ON location "
               f"(longitude, latitude, COALESCE(address_1, '-1'), "
               f"COALESCE(address_2, '-1'), country_id, city_id);")
    ...
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    ...
    op.drop_index('unique_loc', table_name='location')
    ...
    # ### end Alembic commands ###

So, I've found out how to create an index with raw query. All you need is generate new migration with flask db migrate and modify both def upgrade() and 'def downgrade`:

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    ...
    op.execute(f"CREATE UNIQUE INDEX unique_loc ON location "
               f"(longitude, latitude, COALESCE(address_1, '-1'), "
               f"COALESCE(address_2, '-1'), country_id, city_id);")
    ...
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    ...
    op.drop_index('unique_loc', table_name='location')
    ...
    # ### end Alembic commands ###
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文