Sqlalchemy中的复合键

Pra*_*har 12 python sqlalchemy primary-key

我正在flask-sqlalchemy构建一个webapp,我有以下模型:

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    candidates = db.relationship('Candidate', backref='post', lazy='dynamic')

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Post %r>" % self.name

class Candidate(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), primary_key=True)
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
    hostel = db.Column(db.String(80))
    yes_no = db.Column(db.Boolean)
    #votes = db.relationship('Vote', backref='vote', lazy="dynamic")

    def __init__(self, name, hostel, post_id, yes_no):
        self.name = name
        self.hostel = hostel
        self.post_id = post_id
        self.yes_no = yes_no

    def __repr__(self):
        return "<Candidate: %r, Post: %r>" % (self.name, self.post.name)
Run Code Online (Sandbox Code Playgroud)

在数据库设计方面,我完全是noob,所以我真的很感激我对一些基本查询的一些指示

  • id栏是否必要?我见过的大多数教程都将其作为专栏(具体为主键).我可以不用它吗?特别是在我有另一个主键的情况下?

  • 考虑到post_id是外键,如何在Candidate#Name和Candidate#post_id列上有一个复合键约束.

  • 如何"刷新"我的数据库.在我对模型进行更改后,如何确保这些更改反映在实际表中?我需要drop_allcreate_all手动?

  • 最后,sqlalchemy文档是否也适用flask-sqlalchemy于此?

jad*_*k94 22

id列是否必要?我见过的大多数教程都将其作为专栏(具体为主键).我可以不用它吗?特别是在我有另一个主键的情况下?

对于邮政表,是的.对于另一个,没有.有些人可能会争辩说,因为name是唯一的,所以将它作为主键,但这意味着在任何需要引用该帖子的位置使用该名称,这意味着更多空间(名称与int的长度)(不一定是问题)和想一想"如果候选人姓名发生变化怎么办?".但是,你当然不需要两者.

考虑到post_id是外键,如何在Candidate#Name和Candidate#post_id列上有一个复合键约束.

您是如何做到的,每个帖子都分配到一个帖子:

candidates = db.relationship('Candidate', backref='post', lazy='dynamic')
Run Code Online (Sandbox Code Playgroud)

因此,不应该调用该字段,candidates而是candidate要有意义.

要回答你的问题,我将引用文档:

要在约束/索引中指定多个列或指定显式名称,请显式使用UniqueConstraint或Index构造.

您需要将其添加到模型定义中:

__table_args__ = (
        UniqueConstraint("id", "candidate_id"),
    )
Run Code Online (Sandbox Code Playgroud)

虽然我认为它在这里没用(你为什么需要它?如果id是唯一的(主键),那么包含它的任何其他组合将是唯一的)...

如何"刷新"我的数据库.在我对模型进行更改后,如何确保这些更改反映在实际表中?我需要手动drop_all和create_all吗?

您需要对commit数据库进行更改.来自flask-sqlalchemy的文档:

db.session.add(post)
db.session.commit()
Run Code Online (Sandbox Code Playgroud)

最后,sqlalchemy文档是否也适用于flask-sqlalchemy?

注意这是我自己发现的,没有"官方"来源,只需阅读flask-sqlalchemy的来源.

是的,不同之处在于您访问模型以及会话和引擎的方式......例如,在sqlalchemy中:

from sqlalchemy.orm import sessionmaker
Session = sessionmaker()
session = session()
session.commit()
Run Code Online (Sandbox Code Playgroud)

在flask-sqlalchemy中:

db.session.commit()
Run Code Online (Sandbox Code Playgroud)

对于"模特":

# In sqlalchemy
Base = declarative_base()
class Post(Base):
    # ...

# In flask-sqlalchemy
class Post(db.Model):
    # ...
Run Code Online (Sandbox Code Playgroud)

等等...

无论如何,你以sqlalchemy的方式做什么,你做了一次,而flask-sqlalchemy在后台为你做了.

希望它有帮助:)(这不仅仅是关于sqlalchemy中复合键的一个问题...)

  • @PiotrKamoda 如果您需要复合主键,只需将 `primary_key=True` 设置为所有主键字段。或者在 `__table_args__` 中使用类似于 `UniqueConstraint("id", "candidate_id")` 的东西。您甚至可以在表 args 中指定更复杂的主键。 (3认同)
  • soooo ...如何添加组合键? (2认同)