Python 如何防止在SQLAlchemy一对多关系中重新创建孩子?

Python 如何防止在SQLAlchemy一对多关系中重新创建孩子?,python,sqlalchemy,Python,Sqlalchemy,我正在使用Python 2.6.6和SQLAlchemy 0.6.6来处理数据库中的一对多关系,并且不确定如何防止SQLAlchemy在已经存在类似数据的情况下添加新的子记录 数据库代码: from sqlalchemy import * from sqlalchemy.orm import backref, relationship, sessionmaker, create_session from sqlalchemy.ext.declarative import declarative_

我正在使用Python 2.6.6和SQLAlchemy 0.6.6来处理数据库中的一对多关系,并且不确定如何防止SQLAlchemy在已经存在类似数据的情况下添加新的子记录

数据库代码:

from sqlalchemy import *
from sqlalchemy.orm import backref, relationship, sessionmaker, create_session
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

# Parent table, no foreign key.
class Author(Base):
    __tablename__ = 'authors'

    id = Column(Integer, primary_key=True)
    username = Column(String)
    author_metadata = relationship('AuthorMetadata', backref='author')

# Child table, many records with same author_id.
class AuthorMetadata(Base):
    __tablename__ = 'author_metadata'

    id = Column(Integer, primary_key=True)
    author_id = Column(Integer, ForeignKey('authors.id'))
    metakey = Column(String)
    metavalue = Column(Text)
示例脚本:

if __name__ == '__main__':
    engine = create_engine('database_details', pool_recycle=90)
    session = create_session(bind=engine)

    author = session.query(Author).filter_by(username='Godfrey').first()
    if not author:
        author = Author()
    author.username = 'Godfrey'
    author.author_metadata = [
        AuthorMetadata(metakey='location', metavalue='New York'),
        AuthorMetadata(metakey='posts', metavalue='5')]
    session.add(author)
    session.flush()
第一次运行示例脚本时,数据库中会显示以下内容(如预期的那样):

但是,如果我再次运行示例脚本,您可以看到现有元数据记录的作者ID已设置为null,并且插入了新记录:

dev=# select id, author_id, metakey, metavalue from author_metadata order by id desc limit 4;
  id   | author_id | metakey  | metavalue 
-------+-----------+----------+-----------
 85092 |      5025 | posts    | 5
 85091 |      5025 | location | New York
 85090 |           | posts    | 5
 85089 |           | location | New York
(4 rows)

我并不觉得奇怪,但是我想知道是否有一种很好的方法可以与SQLAlchemy进行通信,即如果新的元数据列表与现有列表不同,SQLAlchemy应该只插入/修改/删除作者元数据行。

您可以明确地检查列表的内容,如果不存在新的AuthorMetadata对象,则只附加它们,而不是删除整个集合并使用全新对象重新创建它。这至少可以避免丢弃以前创建的记录


您的用例匹配且非常好,因此您可能希望使用其中一个。

谢谢jd和Mark!我使用了你关于映射集合和关联代理的建议,并提出了我想要的。
dev=# select id, author_id, metakey, metavalue from author_metadata order by id desc limit 4;
  id   | author_id | metakey  | metavalue 
-------+-----------+----------+-----------
 85092 |      5025 | posts    | 5
 85091 |      5025 | location | New York
 85090 |           | posts    | 5
 85089 |           | location | New York
(4 rows)