Sqalchemy用整数替换文本

时间:2017-11-06 13:37:11

标签: python sqlalchemy associations

我正在使用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()类对象,而不是简单的整数。

1 个答案:

答案 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食谱。