Python SQLAlchemy中插入行的正确模式

Python SQLAlchemy中插入行的正确模式,python,sqlalchemy,Python,Sqlalchemy,我有一个有点复杂的插入操作,它归结为: 输入:标签列表,书名 将值(图书名称)插入图书(图书名称) 对于每个标签: 如果标签不存在: 插入标签(标签名称)值(标签名称) 插入图书标签(图书id,标签id)值(图书id,标签id) 我能比仅仅用SQLALchemy语法编写更简单吗?简短回答:在关联代理的定义中使用自定义创建者: def _tag_find_or_create(tag_name): tag = Tag.query.filter_by(tag_name=tag_na

我有一个有点复杂的插入操作,它归结为:

  • 输入:标签列表,书名
  • 将值(图书名称)插入图书(图书名称)
  • 对于每个标签:
    • 如果标签不存在:
      • 插入标签(标签名称)值(标签名称
    • 插入图书标签(图书id,标签id)值(图书id标签id

我能比仅仅用SQLALchemy语法编写更简单吗?

简短回答:
关联代理的定义中使用自定义
创建者

def _tag_find_or_create(tag_name):
    tag = Tag.query.filter_by(tag_name=tag_name).first()
    return tag or Tag(tag_name=tag_name)


class Book(Base):
    __tablename__ = 'book'
    id = Column(Integer, primary_key=True)
    book_name = Column(String)

    # relationship
    _tags = relationship('Tag', secondary='book_tag')
    tags = association_proxy('_tags', 'tag_name', creator=_tag_find_or_create)

详细回答:下面的代码是一个独立的工作示例。关于实施的几句话:

  • 我们使用以简化
    多对多
    关系。仔细阅读这整页
  • 特别是,我们重新定义了默认函数,它将首先查询数据库/会话以检查
    标记
    ,如果找不到,则创建一个
代码:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy import UniqueConstraint, ForeignKey
from sqlalchemy.orm import relationship, scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy

# Configure test data SA
engine = create_engine('sqlite:///:memory:', echo=True)
session = scoped_session(sessionmaker(bind=engine))
Base = declarative_base(engine)
Base.query = session.query_property()


def _tag_find_or_create(tag_name):
    tag = Tag.query.filter_by(tag_name=tag_name).first()
    return tag or Tag(tag_name=tag_name)


class Book(Base):
    __tablename__ = 'book'
    id = Column(Integer, primary_key=True)
    book_name = Column(String)

    # relationship
    _tags = relationship('Tag', secondary='book_tag')
    tags = association_proxy('_tags', 'tag_name', creator=_tag_find_or_create)


class BookTag(Base):
    __tablename__ = 'book_tag'
    __tableargs__ = (UniqueConstraint('book_id', 'tag_id', name='book_tag_uc'),)

    id = Column(Integer, primary_key=True)
    book_id = Column(Integer, ForeignKey('book.id'))
    tag_id = Column(Integer, ForeignKey('tag.id'))


class Tag(Base):
    __tablename__ = 'tag'
    id = Column(Integer, primary_key=True)
    tag_name = Column(String, unique=True)


# CREATE SCHEMA
Base.metadata.create_all()


def _insert_test_data():
    book = Book(book_name="book-1")
    book.tags.append("fiction")
    book.tags.append("history")
    session.add(book)
    session.commit()

    assert 1 == len(Book.query.all())
    assert 2 == len(Tag.query.all())

    book2 = Book(book_name="book-2")
    book2.tags.append("history")
    book2.tags.append("crime")
    session.add(book2)
    session.commit()

    assert 2 == len(Book.query.all())
    assert 3 == len(Tag.query.all())


def _add_new_book(book_name, tags):
    book = Book.query.filter(Book.book_name == book_name).first()
    assert not(book), "Book with name '{}' already found [{}]".format(
        book_name, book)

    book = Book(book_name=book_name)
    for tag in tags:
        book.tags.append(tag)
    session.add(book)
    session.commit()


if __name__ == '__main__':
    _insert_test_data()
    _add_new_book('SuperMan', ['fiction', 'romance'])

我知道这是徒劳的,但你用知识杀了我。谢谢我知道SQLALchemy比简单的查询更复杂:)不复杂,相当强大和复杂。