Может ли кто-нибудь помочь мне понять следующее поведение?У меня есть простая схема, где у проекта много активов и элементов.Активы и элементы имеют отношение «многие ко многим» в рамках проекта.
Мне нужно убедиться, что элемент имеет уникальный код в рамках проекта, поэтому прежде чем добавлять новыйЭлемент сеанса SQLAlchemy Я хотел бы проверить, существует ли элемент с таким же кодом в проекте.Я обнаружил, что когда я использую таблицу ассоциаций для сопоставления взаимосвязи «многие ко многим» между элементами и активами, я не могу запрашивать базу данных без действия запроса, фактически фиксирующего новый элемент в базе данных.
Чтобы было ясно, я не добавил 'ed или commit ' ed этот новый элемент в сеанс SQLAlchemy на данный момент.
from sqlalchemy import create_engine, and_
from sqlalchemy import Table, Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relation, backref
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.associationproxy import association_proxy
### your credentials here ###
# _MYSQL_DB =
# _MYSQL_USER =
# _MYSQL_PWORD =
# _MYSQL_SCHEMATA =
# _MYSQL_TEST_SCHEMATA =
testEngine = create_engine("mysql://%s:%s@%s/%s"%( _MYSQL_USER,
_MYSQL_PWORD,
_MYSQL_DB,
_MYSQL_TEST_SCHEMATA),
pool_recycle=3600,
echo=True)
Base = declarative_base()
SQLAlchemySession = sessionmaker(autoflush=True, autocommit=False)
class Project(Base):
__tablename__ = "SA_project_t"
id = Column(Integer, primary_key=True, autoincrement=True)
code = Column(String(24), nullable=False, unique=True)
class Asset(Base):
__tablename__ = "SA_asset_t"
id = Column(Integer, primary_key=True, autoincrement=True)
projectId = Column(Integer, ForeignKey("SA_project_t.id"))
project = relation("Project")
code = Column(String(128))
element_to_asset_assoc = Table( "SA_elementToAssetAssoc_t",
Base.metadata,
Column("elementId", Integer, ForeignKey("SA_element_t.id")),
Column("assetId", Integer, ForeignKey("SA_asset_t.id")))
class Element(Base):
__tablename__ = "SA_element_t"
id = Column(Integer, primary_key=True, autoincrement=True)
projectId = Column(Integer, ForeignKey("SA_project_t.id"))
project = relation("Project")
code = Column(String(256))
assets = relation("Asset", secondary=element_to_asset_assoc, backref="elements")
Base.metadata.bind=testEngine
session = SQLAlchemySession(bind=testEngine)
Base.metadata.drop_all(checkfirst=True)
Base.metadata.create_all(testEngine, checkfirst=True)
# Create a Project, Asset and Element
project = Project()
project.code = "MyProject"
session.add(project)
asset = Asset()
asset.project = project
asset.code = "MyAsset"
session.add(asset)
element = Element()
element.project = project
element.code = "MyElement"
element.assets = [asset]
session.add(element)
session.commit()
# Now I'd like to add a new element, but first check that the
# element's code is unique within the scope of the Project
newElement = Element()
newElement.project = project
newElement.code = "MyElement"
newElement.assets = [asset]
results = session.query(Element).filter(and_( Element.project==newElement.project,
Element.code==newElement.code))
# Up until this point, newElement hasn't been inserted into the
# database, but once I query "results.count()" I find that an INSERT
# has been perfomed.
print results.count()
# p.s. I realize that results will contain both the original and
# new element, but I don't expect the new element to have been
# inserted into the database at this point.
Действие вызова count () для переменной results передает newElement в базу данных MySQL, что не является моим намерением.Если я удаляю таблицу ассоциации, то получаю ожидаемое поведение - newElement не добавляется в БД.
Из того, что я вижу из журнала, сеанс видит связанный активкак грязный в начале запроса, и сброс этого вызывает фиксацию newElement .Это ожидаемое поведение?Если это так, есть ли способ сохранить отношение «многие ко многим», все еще запрашивая базу данных в этих условиях и не , инициирующую принятие.
Использование SQLAlchemy 0.7.4