0

I am changing my old SQL implementations of a web app to flask-alchemy and having some difficulties about the correspondence.

The old code looks like this. It does the name query about some properties and returns a csv style text.

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

The new code

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

I am not happy with the new code since it's so verbose.

  • Is there a way to select only the ones in cols instead of query all columns and then pick the needed columns?
  • If not, is it possible to write the ','.join() more succinctly? It seems user['id'] does not work and I have to do user.id.
nos
  • 19,875
  • 27
  • 98
  • 134

2 Answers2

1

If you just want a result set as before, you can do:

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

and then you can use results as you did before.

If, OTOH, you want to use the ORM, you can use 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)
univerio
  • 19,548
  • 3
  • 66
  • 68
1

As it seems that you want to output comma separated values, use the proper module for that. You can override the query's entities with 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()

If you're still on python 2, replace io.StringIO with io.BytesIO.

Community
  • 1
  • 1
Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127