2010-05-13 26 views
7

Tôi đã cập nhật SQLAlchemy thành 0.6 nhưng nó đã phá vỡ mọi thứ. Tôi đã nhận thấy nó trả về tuple không phải là từ điển nữa. Đây là truy vấn mẫu:SQLAlchemy trả về bộ tuple không phải từ điển

query = session.query(User.id, User.username, User.email).filter(and_(User.id == id, User.username == username)).limit(1) 
result = session.execute(query).fetchone() 

Đoạn mã này dùng để trả lại từ điển trong 0,5.

Câu hỏi của tôi là làm cách nào để tôi có thể trả lại một từ điển?

+2

Chỉ cần tò mò: Tại sao bạn không làm 'session.query (Người dùng) .get (id)' (giả sử User.id là khóa chính) . Hoặc 'session.query (User) .filter (User.id == id) .filter (User.username == tên người dùng) .first()' nếu id không phải là khóa chính. Làm điều đó, và bạn sẽ lấy lại một cá thể User, và bạn có thể truy cập các giá trị trường bằng tra cứu thuộc tính. – codeape

Trả lời

5

Điều này sẽ hoạt động: dict(zip(['id','username','email'],result)) (hoặc bạn có thể sử dụng hiểu từ điển nếu bạn đang sử dụng Python 3.x).
Ngoài ra, bạn không cần phải gọi session.execute trên đối tượng session.query. Thay vào đó, bạn sẽ muốn sử dụng phương thức .one(). Điều này cũng làm giảm sự cần thiết cho cuộc gọi .limit(1) treo ở cuối truy vấn của bạn.

+0

Có, nó hoạt động. Cảm ơn. Tôi sử dụng giới hạn (1) bởi vì khi tôi nhìn vào câu lệnh SQL SQLALchemy tạo ra cho mã này, nó không bao gồm LIMIT 1 trong truy vấn. – Ivan

8

Bạn có chắc chắn đó không phải là một ResultProxy giả vờ là một bộ dữ liệu khi bạn in nó? Nhiều đối tượng trong ORM không phải là những gì mà hàm trả về của hàm __str__.

+0

+1 Tôi hoàn toàn bị mù bởi những gì tôi đã nhìn thấy cho đến khi tôi đọc điều này. Sau khi tôi đọc, tôi đã tiếp tục và thử sử dụng tên trường và nó hoạt động hoàn hảo! Đã cứu tôi rất nhiều đau đầu. Cảm ơn. –

33

session.execute chưa bao giờ trở lại một dict, nó sẽ trả về một đối tượng RowProxy, mà có thể được lập chỉ mục như một dict bằng cách sử dụng các phím số nguyên cho tra cứu vị trí, phím chuỗi cho nhãn dựa tra cứu lên hoặc cột đối tượng để tra cứu giá trị của cột đó. Vấn đề ở đây là session.execute(query) không làm những gì bạn có vẻ mong đợi. Nó chuyển đổi đối tượng Query thành câu lệnh Select, thực hiện điều đó và trả về kết quả trực tiếp. Kết quả không biết gì về các tính năng mức ORM. Điều gì đã thay đổi giữa 0,5 quảng cáo 0.6 là ORM sử dụng một thuật toán khác nhau để gắn nhãn các cột trong truy vấn, bây giờ nó sẽ thêm tên bảng vào nhãn. Vì vậy, khi trước đây row['id'] đã xảy ra để hoạt động, hiện tại row['users_id'] hoạt động. Trong cả hai trường hợp, row[User.__table__.columns['id']] đều hoạt động.

Để thực hiện truy vấn ORM, bạn thực sự nên sử dụng các phương pháp .all(), .first().one() hoặc lặp lại qua hoặc sử dụng lập chỉ mục bằng số. Truy vấn trả về các đối tượng có tên tuple. Hãy nén tuple bằng các khóa của nó nếu bạn muốn một dict:

row = session.query(User.id, User.username, User.email)\ 
    .filter(and_(User.id == id, User.username == username)).first() 
print("id=%s username=%s email=%s" % row) # positional 
print(row.id, row.username) # by label 
print(dict(zip(row.keys(), row))) # as a dict 
Các vấn đề liên quan