从 sqlalchemy orm 中的 2 个 csv 文件定义函数

define function from 2 csv files in sqlalchemy orm

我有 2 个 csv 文件。

一个文件(id.csv)包含2列,ID和Names。

另一个csv(relations.csv)也包含2列,TeacherID和StudentID。此文件用于根据学生的 ID 显示特定教师正在教多少学生。

第一个 csv 文件:

ID    Name
ID01  John
ID02  Jane
ID03  Tom
ID04  Bill
ID05  Steve
ID06  Sarah

第二个 csv 文件:

TeacherID  StudentID
ID01       ID03
ID01       ID04
ID02       ID06
ID01       ID05

我已经写了 2 类,ID 和关系,定义表名、列(字符串)、关系和外键。

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Enum, Float, ForeignKey
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import relationship

Base = declarative_base()

class ID(Base):
    __tablename__ = "id"
    index = Column(String, primary_key=True)
    name = Column(String)
    def __repr__(self):
        return "%s %s" %(self.index, self.name)

class Relations(Base):
    __tablename__ = 'relations'
    aindex = Column('ID', Integer, primary_key=True)
    frompax = Column(String, ForeignKey("id.index"))
    topax = Column(String, ForeignKey('id.index'))
    rsfrom = relationship("ID", foreign_keys="Relations.frompax")
    rsto = relationship("ID", foreign_keys="Relations.topax")
    def __repr__(self):
        return "%s %s" %(self.frompax, self.topax)

#Create database engine
engine = create_engine('sqlite:///test', echo=True)
engine
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

#Read the CSV files
import csv
with open('id.csv') as f:
    reader = csv.reader(f)
    header = next(reader)
    for row in reader:
        person = ID(
            index=row[0],
            name=row[1]
        )
        session.add(person)
        session.commit()
        
with open('relations.csv') as f:
    reader = csv.reader(f)
    header = next(reader)
    for row in reader:
        rel = Acquaintance(
            frompax=row[0],
            topax=row[1],
        )
        session.add(rel)
        session.commit()

我想写一个函数,当我输入老师的 ID 时,它会 return he/she 教过的所有学生的名字。到目前为止,我已经设法编写了功能代码,并且 return 学生根据他们的 ID。

def direct(id):
    return list(session.query(Relations).filter_by(frompax=id))

direct('ID01')
[ID01 ID03,
ID01 ID04,
ID01 ID05]

我怎样才能 return 只显示学生姓名? 示例:

direct('ID01')
[Tom,
Bill,
Steve]
import csv
def direct(id):
    id_list = list(session.query(Relations).filter_by(frompax=id))
    name_list = []
    with open("your_first_file.csv", "r") as f:
        reader = csv.reader(f, delimiter='\t')
        for i, line in enumerate(reader):
            if line[0] in id_list:
                name_list.append(line[1])
    return name_list

看起来您正在尝试创建 self-referential many to many relationship。这需要对您的代码进行一些更改以使其与文档中的代码相匹配。

首先,将Relations转换成Table with two columns (note that it uses the same metadata作为模型):

Base = declarative_base()


relations_table = Table(
    'relations',
    Base.metadata,
    Column('frompax', String, ForeignKey('id.index')),
    Column('topax', String, ForeignKey('id.index')),
)

将关系移动到ID;它们可以表示为单一关系。

class ID(Base):
    __tablename__ = 'id'
    index = Column(String, primary_key=True)
    name = Column(String)
    # ID's that have this row as relation.
    has_relations = relationship(
        'ID',
        secondary=relations_table,
        primaryjoin=index == relations_table.c.topax,
        secondaryjoin=index == relations_table.c.frompax,
        backref='is_related_to',
    )

    def __repr__(self):
        return '%s %s' % (self.index, self.name)

最后,更改direct函数,使用Session.get, and then use a list comprehension通过主键获取ID,收集相关对象的名称。

def direct(id_):
    instance = session.get(ID, id_)
    return [r.name for r in instance.is_related_to]