我正在使用Sqlalchemy设计一个用于记录实验室测量的数据库。我为每个测试结果都有一个表格。我想将测试结果和名称标签存储在同一行中。每当我运行相同的测试时,名称标签可以多次出现。因此,我不想多次存储实际标签,而是想用整数替换每个标签。整数将是另一个只存储标签的表的键。
数据库表定义如下:
from sqlalchemy import Column, Integer, String, Float ,
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class TestResults(Base):
__tablename__ = "test_results"
id = Column(Integer, primary_key=True)
test_name = Column(Integer) # id value in TestNames table
timestamp = Column(Integer)
test_value = Column(Float)
class TestNames(Base):
"""
Lookup table for test_name column in TestResults
"""
__tablename__ = 'test_names'
id = Column(Integer, primary_key=True)
name = Column(String)
理想情况下,我希望能够通过输入test_name作为字符串将数据输入TestResults表,例如
results = TestResults()
results.test_name = 'my_test'
results.test_value = 10.1
为了做到这一点,我想我需要一个中间函数来检查我输入到test.ames中的字符串是否已存在于TestNames表中,如果确实存在,那么'real'results.test_name将填入id号对于现有名称。如果该名称不存在,则将其添加到TestNames,并将新名称的id填充到results.test_name中。执行此操作的功能将是这样的:
def test_name_creator(session,name):
"""
Input
-------
session : sqlalchemy session object
name : str
New test name
Output
--------
id : int
id of test name
"""
# Check if name already exists
name_query = session.query(TestNames).filter(TestNames.name==name).all()
if name_query!=[]:
name_id = name_query[0].id
return name_id
# name does not exist, add to TestNames() table
new_test_name = TestNames()
new_test_name.name = name
session.add(new_test_name)
session.commit()
return new_test_name.id
我无法理解的是如何使用上面的函数拦截results.test_name ='my_test'的设置,以便返回的id实际填充到results.test_name中。我认为这是association_proxy + creator函数的工作,但我看到的所有示例都返回Sqlalchemy declarative_base()类对象,而不是简单的整数。
答案 0 :(得分:2)
而不是test_name_creator
返回ID,返回实例本身,如下所示:
def test_name_creator(session, name):
inst = session.query(TestNames).filter(TestNames.name == name).first()
if inst is None:
# Create new TestNames() instance and add to database
inst = TestNames(name=name)
session.add(inst)
return inst
然后,建立一个关系,以便SQLAlchemy确定将ID放在何处:
class TestResults(Base):
...
test_name_id = Column(Integer, ForeignKey(TestNames.id))
test_name = relationship(TestNames)
您可以设置如下名称:
results = TestResults(test_name=test_name_creator(session, "my_test"), value=10.1)
如果您希望将test_name
作为string
的使用模式保留为TestNames
但可以在"image/svg+xml"
中创建行,则可以使用association proxies结合UniqueObject食谱。