2016-09-23 121 views
0

我正在将旧的Web应用程序的SQL实现更改为flask-alchemy,并且对通信有一些困难。将SQL查询转换为flask-sqlalchemy语句

旧代码看起来像这样。它执行关于某些属性的名称查询并返回csv样式文本。

header = 'id,display_name,city,state,latitude,longitude\n' 
base_query = '''SELECT id, bbs_id, city, state, 
        latitude, longitude FROM mytable''' 
conn = sqlite3.connect(path.join(ROOT,'db.sqlite')) 
c = conn.execute(base_query+'WHERE name=?', (name,)) 
results = c.fetchall() 
conn.close() 
rows = [','.join(map(str, row)) for row in results] 
return header + rows 

新的代码

header = 'id,display_name,city,state,latitude,longitude\n' 
cols = ['id', 'bbs_id', 'city', 'state', 'latitude', 'longitude'] 
users = User.query.filter_by(name=name).all() 
rows = '' 
for user in users: 
    rows += ','.join([user.id, user.bbs_id, user.city, user.state, user.latitude, user.longitude]) + '\n' 
return header + rows 

我不开心的用新的代码,因为它是如此冗长。

  • 有没有办法只选择cols而不是查询所有列,然后选择需要的列?
  • 如果没有,是否可以更简洁地编写','.join()?看来user['id']不起作用,我必须做user.id

回答

1

,因为它似乎要输出逗号分隔值,使用proper module了点。你可以用with_entities覆盖查询的实体:

import csv 
import io 

... 

output = io.StringIO() 
writer = csv.writer(output) 

headers = ['id', 'bbs_id', 'city', 'state', 'latitude', 'longitude'] 
writer.writerow(headers) 

# The other option is to db.session.query(...) 
users = User.query.with_entities(
    *(getattr(User, hdr) for hdr in headers) 
).filter_by(name=name) 
writer.writerows(users) 

return output.getvalue() 

如果你还在蟒2,replace io.StringIO with io.BytesIO

1

如果你只是想为之前设定的结果,你可以这样做:

results = db.session.query(*(getattr(User, col) for col in cols)).filter_by(...) 

,然后你可以使用results像之前。

如果OTOH,你要使用ORM,你可以使用load_only

users = User.query.options(*(load_only(col) for col in cols)).filter_by(...) 
rows = "".join(",".join(*(getattr(u, col) for col in cols)) + "\n" for u in users) 
+0

'filter_by(name = name)'? – nos

+0

@nos添加到示例。 – univerio