【问题标题】:creating and appending to a list in SQLAlchemy database table创建并附加到 SQLAlchemy 数据库表中的列表
【发布时间】:2019-02-22 18:07:55
【问题描述】:

我正在学习 SQLAlchemy,但我被卡住了。 我有一个 SQL 表(table1)有两个字段:'name' 和 'other_names'

我有一个包含两列的 excel 文件:

first_name alias   
paul   patrick
john   joe
simon  simone
john   joey
john   jo

我想将 excel 文件读入我的 table1,使其看起来像这样(即同一行的所有别名都在一行上):

paul    patrick
john    joe,joey,jo
simon   simone

这是我试图做的想法。我尝试过的代码(使用 cmets):

for line in open('file.txt', 'r'): #for each line in the excel file
        line = line.strip().split('\t') #split each line with a name and alias
        first_name = line[0] #first name is the name before the tab
        alias = line[1] #alias is the name after the tab
        instance = 
        Session.query(session,tbs['table1'].name).filter_by(name=first_name) #look through the database table, by name field, and see if the first name is there 
        list_instance = [x[0] for x in instance] #make a list of first names already in database table
        if first_name not in list_instance: #if the excel first name is not in the database table
              alias_list = [] #make an empty list
              alias_list.append(alias) #append the alias
              name_obj = lib.get_or_create( #small function to make db object
              session,
              tbs["table1"],
              name = first_name, #add first name to the name field
              other_names = alias_list # add alias list to the other_names field
            )


       elif first_name in list_instance: #elif first name already in db
             alias_list.append(alias) #append the alias to the alias list made above
             name_obj = lib.get_or_create(
             session,
             tbs["table1"],
             name = first_name,
             other_names = alias_list #create object as before, but use updated alias list
    )

问题是我可以让上面的代码运行没有错误,而且输出不是附加列表,它只是一个看起来像excel文件的数据库表;即

name   alias
paul   patrick
john   joe
simon  simone
john   joey
john   jo

有人可以指出我哪里出错了,具体来说,我该如何修改这段代码?如果问题不清楚,请告诉我,我试图将其作为一个简单的例子。具体来说,我如何初始化并添加到列表中作为 SQLalchemy 数据库表中的字段条目。

更新 1:我已根据下面的建议更新了我的代码。但是我仍然有这个问题。这是完整的目标、代码和测试文件: 目标:

我在数据库中有一个表(请参阅下面的测试文件进入表)。该表有两个字段,名称(拉丁名称,例如智人)和其他名称(常用名称,例如人类,人)。我想更新表中的一个字段(其他名称),所以不要:

Rana rugosa human   
Rana rugosa man 
Rana rugosa frog    
Rana rugosa cow

我有:

Rana rugosa human,man,frog,cow

test_data 文件如下所示:

origin_organism        common_name         tested_organism
Rana rugosa            human                -
Rana rugosa            man                  -
Rana rugosa            frog                 homo sapiens
Rana rugosa            cow                  Rana rugosa
Rana rugosa            frog                 Rana rugosa
Rana rugosa            frog                 -
Rana rugosa            frog                 -
Rana rugosa            frog                homo sapiens
-                      -                   -
-                      -                   homo sapiens
-                      -                   -
-                      -                   -
-                      -                   -
-                      -                   -
streptococcus pneumoniae    -              -

代码:

import sys 
from sqlalchemy.orm  import * 
from sqlalchemy  import * 
from dbn.sqlalchemy_module  import lib 
import pd

engine = lib.get_engine(user="user", psw="pwd", db="db", db_host="111.111.111.11")
Base = lib.get_automapped_base(engine)
session = Session(engine)
tbs = lib.get_mapped_classes(Base)
session.rollback()
df = pd.read_excel('test_data.xlsx', sheet_name = 'test2')




for index, row in df.iterrows():  
    origin_latin_name = row['origin_organism'].strip().lower()
    other_names_name = row['common_name'].strip().lower()
    tested_species = row['tested_organism'].strip().lower()


if origin_latin_name not in [None, "None", "", "-"]:
    instance = [x[0] for x in Session.query(session,tbs['species'].name).filter_by(name=origin_latin_name).all()]
    if origin_latin_name not in instance:
        origin_species = lib.get_or_create(
            session,
            tbs["species"],
            name = origin_latin_name,
            other_names = other_names_name
        )

    elif origin_latin_name in instance:
        other_names_query = Session.query(session,tbs['species'].other_names).filter_by(name=origin_latin_name)
        other_names_query_list = [x for x in other_names_query]
        original_list2 = list(set([y for y in x[0].split(',') for x in other_names_query_list]))
        if other_names_name not in original_list2:
            original_list2.append(other_names_name)
            new_list = ','.join(original_list2)
            new_names = {'other_names':','.join(original_list2)}

        origin_species = lib.get_or_create(
            session,
            tbs["species"],
            name = origin_latin_name,
            other_names = new_list
        )

elif 语句中的部分不起作用。我遇到了两个问题:

(1) 我得到的最新错误: NameError: name 'new_list' 没有定义

(2) 我得到的另一个错误是我还有另一个表

map1 = lib.get_or_create(
    session,
    tbs["map1"],
    age_id_id = age,
    name_id_id = origin_species.id
    )

...它说找不到 origin_species,但我认为这与 elif 语句有关,即不知何故 origin_species 对象未正确更新。

如果有人可以提供帮助,我将不胜感激。

【问题讨论】:

  • 阅读ericlippert.com/2014/03/05/how-to-debug-small-programs 了解如何调试代码的提示。
  • 我认为这对你有用:stackoverflow.com/questions/48799232/…。您可能需要 pd.to_sql() 将 DataFrame 推送到您的数据库
  • 如果条件不执行,elif 下的所有内容都不会被分配。所以elif origin_latin_name in instance
  • 你想做的每一件事都不需要用 SQL 炼金术来完成。您正在导入熊猫。只需将您的表导入 pandas 并使用 groupby 语句。如果你只使用 MySQL alchemy 来保存数据,我愿意告诉你

标签: python sql sqlalchemy


【解决方案1】:

简单的错误。你没有给它一个清单。我不确定为什么它们最终会出现在不同的行中,但是,我会更改以下内容,因为目前我看不到您将名称拆分为列表的位置,我所看到的只是您使用追加。

alias_list = alias.split(',')

也可以是:

alias_list = line[1].split(',')

输出:

alias_list:    ['Name1','Name2','Name3']

目前你的代码输出:

alias_list = ['Name1,Name2,Name3']

虽然它在技术上是按数据类型列出的列表,但对于您想要使用它的方式来说,它是一个毫无价值的列表。这是因为alias_list[0] 会返回整个字符串,而不是'Name1'

警告词:

您的代码不必要地创建了一个列表。您不需要数据库中的列表,您可以通过使用读取 excel 文件时评估的字符串轻松实现您的 wabt。

恕我直言,您应该做的是将名称字符串存储为一个完整的字符串,然后如果您需要查询某人的别名,那么您可以在另一侧拆分字符串,如果这有意义的话?

【讨论】:

  • 谢谢。我已经根据您的建议更新了我的代码(最初我只是为了简单起见更改了变量名称,但我现在将所有数据完全保留为原始数据,只是为了准确显示我所做的事情)。如果您有任何想法,我将不胜感激。
  • 另外,如果有帮助,我在这里找到了一个可能很棒的 StackOverflow 答案:stackoverflow.com/questions/9667138/…,我试图将这些信息应用于这个问题,但我显然做错了。
  • 致@Swift 的警告词:另一种方法可能是直接查询这个并让数据库准备好你的结果 - stackoverflow.com/a/44949384/1896134 祝你好运!
【解决方案2】:

如果您对 pandas 数据框使用 groupby 语句,您可以轻松地做到这一点。代码未经测试,如果有错误请告诉我

import sys 
from sqlalchemy.orm  import * 
from sqlalchemy  import * 
from dbn.sqlalchemy_module  import lib 
import pd

engine = lib.get_engine(user="user", psw="pwd", db="db", db_host="111.111.111.11")

###Get test data
added_df = pd.read_excel('test_data.xlsx', sheet_name = 'test2')

###Get current database as a pandas object
my_current_df = pd.read_sql_table(
        "table1", engine)

#Now group by origin organism
gb = added_df.groupby('origin_organism')

#For every member that had the same origin organism, return it as a comma seperated list into a new dataframe
df = pd.DataFrame(gb.alias.apply(lambda x: ",".join(x)))

#Now append that dataframe onto the one that came from the database
my_current_df.append(df)

#NOw return that dataframe back to the database
my_current_df.to_sql(
        name='table1',
        con=engine,
        if_exists='replace')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-22
    • 1970-01-01
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 2021-06-27
    • 1970-01-01
    相关资源
    最近更新 更多