是否有一种有效的方法来创建对象并立即获得SQLAlchemy中新创建的对象的自动增量ID

时间:2017-07-19 14:22:51

标签: python sqlalchemy flask-sqlalchemy

我想在SQL数据库的额外表中存储对通用目的的数据库条目的引用。

我在SQLAlchemy中的数据模型如下所示:

class Entity(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(10))

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


class Entry(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name= db.Column(db.String(10))

    entity_id = db.Column(db.Integer, db.ForeignKey('entity.id'))

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


class Thing(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name= db.Column(db.String(10))

    entity_id = db.Column(db.Integer, db.ForeignKey('entity.id'))

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

只要创建了条目 Thing entity_id 中就会有一个对实体即可。为了解决这个问题,我首先创建一个实体,提交它,然后从新创建的实体中获取id,并使用抓取的id创建条目 Thing

# Create a new Entity object
entity = Entity(entity_title)

# Commit the entity
db.session.add(entity)
db.session.commit()

# Get the entity ID
entity_id = Entity.query.filter_by(name=entity_title).first().id

# Create a new Entry/Thing object
entry= Entry(name, entity_id)

# Commit the entry
db.session.add(task)
db.session.commit()

这种方式看起来效率很低。还有其他方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

relationships不是手动处理外键,而是提供这样一个目的,即允许您处理对象及其关系的内存表示,而无需按正确顺序执行flush() es找出你应该放在哪里的外键。

class Entry(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name= db.Column(db.String(10))

    entity_id = db.Column(db.Integer, db.ForeignKey('entity.id'))
    entity = relationship(Entity)

entry = Entry(name="foo", entity=Entry(name="foo"))
db.session.add(entry)
db.session.commit()

请注意您根本不必处理entity_id

在您的特定情况下,您可能还会发现inheritance有用:

class Entity(db.Model):
    __tablename__ = "entities"

    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(10))
    type = db.Column(db.Enum("entry", "thing"))

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

    __mapper_args__ = {
        "polymorphic_on": type,
    }

class Entry(Entity):
    __tablename__ = "entries"

    id = db.Column(db.Integer, db.ForeignKey('entity.id') primary_key=True)

class Thing(Entity):
    __tablename__ = "things"

    id = db.Column(db.Integer, db.ForeignKey('entity.id') primary_key=True)

entry = Entry(name="foo")  # automatically deals with the entities table
db.session.add(entry)
db.session.commit()

答案 1 :(得分:0)

您可以使用session.flush()

entity = Entity(entity_title)

# Commit the entity
db.session.add(entity)
db.session.flush()

之后你可能在entity.id中有id session.flush()仅“创建”一个实例,但它实际上没有提交您的会话 在你的情况下

# Create a new Entity object
entity = Entity(entity_title)

# Commit the entity
db.session.add(entity)
db.session.flush()

# Didn't need 
# Get the entity ID
# entity_id = Entity.query.filter_by(name=entity_title).first().id

# Create a new Entry/Thing object
entry= Entry(name, entity.id)

# Commit the entry
db.session.add(task)
db.session.commit()

这里是文档 http://docs.sqlalchemy.org/en/latest/orm/session_api.html#sqlalchemy.orm.session.Session.flush