【发布时间】:2015-06-10 00:21:07
【问题描述】:
我正在尝试使用关联代理来更简单地处理标签式记录,但我遇到了一个问题,即强制唯一性和让对象重用现有标签而不是总是创建新标签。
这是一个类似于我的设置。文档中的示例有一些 enforcing uniqueness 的配方,但它们都依赖于对会话的访问,并且通常需要一个全局会话,而我无法做到这一点。
from sqlalchemy import Column, Integer, String, create_engine, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
Base = declarative_base()
engine = create_engine('sqlite://', echo=True)
Session = sessionmaker(bind=engine)
def _tag_find_or_create(name):
# can't use global objects here, may be multiple sessions and engines
# ?? No access to session here, how to do a query
tag = session.query(Tag).filter_by(name=name).first()
tag = Tag.query.filter_by(name=name).first()
if not tag:
tag = Tag(name=name)
return tag
class Item(Base)
__tablename__ = 'item'
id = Column(Integer, primary_key=True)
tags = relationship('Tag', secondary='itemtag')
tagnames = association_proxy('tags', 'name', creator=_tag_find_or_create)
class ItemTag(Base)
__tablename__ = 'itemtag'
id = Column(Integer, primary_key=True)
item_id = Column(Integer, ForeignKey('item.id'))
tag_id = Column(Integer, ForeignKey('tag.id'))
class Tag(Base)
__tablename__ = 'tag'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
# Scenario 1
session = Session()
item = Item()
session.add(item)
item.tagnames.append('red')
# Scenario 2
item2 = Item()
item2.tagnames.append('blue')
item2.tagnames.append('red')
session.add(item2)
如果没有 creator 功能,我只会得到大量重复的 Tag 项。 creator 函数似乎是进行此类检查的最明显位置,但我不确定如何从 creator 函数内部进行查询。
考虑示例底部提供的两种方案。在第一个示例中,似乎应该有一种方法可以在 creator 函数中访问会话,因为要添加标签的对象已经与会话相关联。
在第二个示例中,Item 对象尚未与会话关联,因此验证检查无法在 creator 函数中进行。当对象实际添加到会话中时,它必须稍后发生。
对于第一种情况,我将如何访问 creator 函数中的会话对象?
对于第二种情况,有没有办法“监听” 何时将父对象添加到会话并在那时验证关联代理?
【问题讨论】:
标签: python database orm sqlalchemy