2016-09-23 75 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