2012-05-16 39 views
6

Câu hỏi của tôi thực sự là cách thiết lập mô hình khai báo SQLAlchemy có thể được truy cập từ lớp QTableView của PySide.Thiết kế mô hình '' cho QTableView trong PySide + SQLAlchemy.

Tôi chỉ cố gắng để về cơ bản thực hiện một giao diện người cho Object Relational tutorial

Đáng tiếc là tôi có một vài điểm của sự nhầm lẫn. Tôi sẽ cố gắng giải thích tôi đang ở đâu.

Tôi đã làm theo hướng dẫn SQLAlchemy đến điểm mà tôi có hai bảng có liên quan và có thể thao tác/truy vấn những người không có vấn đề gì. Việc cố gắng thiết lập một số QTableView class rõ ràng yêu cầu setData() method bằng mô hình của riêng tôi hoặc sử dụng mô hình mặc định yêu cầu setItem() method.

Vì vậy, câu hỏi là cách thiết kế mô hình. Tôi đoán điều này có nghĩa là xác định một trong hai phương thức đó để truy vấn/sửa đổi cơ sở dữ liệu. Tôi không biết đúng cách để làm điều này.

Mô hình được cho là giống như tên người dùng và họ được lặp lại trên một vài hàng cho đến khi tất cả các địa chỉ được hiển thị, sau đó chuyển sang Người dùng tiếp theo. Tôi có thể làm điều này với lồng cho vòng để in này tại dấu nhắc nhưng tôi không nghĩ rằng làm cho một danh sách lớn là con đường để đi như là dường như để đánh bại các điểm có cơ sở dữ liệu ở nơi đầu tiên ...

Tôi cũng không biết điều gì sẽ xảy ra khi cơ sở dữ liệu phát triển, toàn bộ bảng có được khởi tạo và giữ trong bộ nhớ hay Qt tải hàng và cột khi chúng đến để xem khi người dùng cuộn?

Rất nhiều văn bản ở đây xin lỗi, nhưng cố gắng rõ ràng. Nếu có thêm bất kỳ thứ gì tôi có thể thêm, hãy cho tôi biết. Hoặc nếu tôi hoàn toàn theo dõi sai ...

from PySide import QtCore, QtGui 
from sqlalchemy import Column, Integer, String, Text, Sequence, ForeignKey, Date, Boolean, create_engine 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker, relationship, backref, aliased 
import datetime 


engine = create_engine('sqlite:///reminder.db') 

Base = declarative_base() 

class User(Base): 
    __tablename__ = 'users_db' 
    id = Column(Integer, Sequence('user_id_seq'), primary_key=True) 
    lastname = Column(String) 
    firstname = Column(String) 
    contact = Column(String) 
    history = Column(Text) 
    notes = Column(Text) 

    addresses = relationship('Address', order_by='Address.id', 
           backref='user', cascade='all, delete, delete-orphan') 


    def __init__(self, firstname, lastname, contact): 
     self.firstname = firstname 
     self.lastname = lastname 
     self.contact = contact 

    def __repr__(self): 
     return "<User('{0}', '{1}', '{2}')>".format(self.firstname, self.lastname, self.contact) 


class Address(Base): 
    __tablename__ = 'addresses_db' 
    id = Column(Integer, primary_key=True) 
    address = Column(String(150)) 
    date = Column(Date) 
    check1 = Column(Boolean) 
    check2 = Column(Boolean) 

    user_id = Column(Integer, ForeignKey('users_db.id')) 

    def __init__(self, address, date): 
     self.address = address 
     self.date = date 
     self.check1 = False 
     self.check2 = False 

    def __repr__(self): 
     return "<Address('{0}', '{1}')>".format(self.address, self.date) 

if __name__ == '__main__': 
    Base.metadata.create_all(engine) 
    Session = sessionmaker(bind=engine) 
    session = Session() 
    header = [User.firstname, User.lastname, nextaddressfromUser] 

>>> for user in session.query(User).all(): 
...  for addr in user.addresses: 
...   print user.firstname, user.lastname, addr.address 

Trả lời

6

Trước tiên, hãy quên truy vấn và sử dụng vòng lặp bạn đang sử dụng. Những gì bạn đang tìm kiếm trong giao diện người dùng là một điều cơ bản. Tôi đã tìm thấy từ việc thiếu tài liệu, cách tốt nhất là sử dụng QTableWidget (hoặc bất kỳ thứ gì QWhateverWidget) tốt hơn QWhateverView cho những thứ cơ bản. Bạn không cần phải xác định mô hình của riêng bạn cho những điều đơn giản. Vì vậy, tôi sẽ cho bạn thấy làm thế nào để làm điều đó với một QTableWidget. Bạn cần tạo một QTableWidgetItem cho mỗi ô tại (hàng, cột). Một vấn đề tôi gặp phải, là phải thiết lập số hàng trước khi thêm chúng. Dù sao, ở đây:

import sys 
from PySide import QtGui, QtCore 

class Test(QtGui.QWidget): 

    def __init__(self, rows): 
     super(Test, self).__init__() 

     self.table = QtGui.QTableWidget() 
     self.table.setColumnCount(3) 
     # Optional, set the labels that show on top 
     self.table.setHorizontalHeaderLabels(("First Name", "Last Name", "Address")) 

     self.table.setRowCount(len(rows)) 
     for row, cols in enumerate(rows): 
      for col, text in enumerate(cols): 
       table_item = QtGui.QTableWidgetItem(text) 
       # Optional, but very useful. 
       table_item.setData(QtCore.Qt.UserRole+1, user) 
       self.table.setItem(row, col, table_item) 

     # Also optional. Will fit the cells to its contents. 
     self.table.resizeColumnsToContents() 

     # Just display the table here. 
     layout = QtGui.QHBoxLayout() 
     layout.addWidget(self.table) 
     self.setLayout(layout) 

if __name__ == "__main__": 
    # ... 
    rows = [] 
    # Here I have to fill it in an array, because you need to know the number of rows before adding... There might be a better solution though. 
    for user in session.query(User).all(): 
     for addr in user.addresses: 
      # These are the columns on each row (firstname, lastname, address) 
      rows.append((user.firstname, user.lastname, addr.address)) 

    app = QtGui.QApplication(sys.argv) 
    test = Test(rows) 
    test.show() 
    app.exec_() 

Một điều bạn có thể xem xét sử dụng là một QTreeWidget, mà hỗ trợ nhiều cột, và bạn có thể làm cho nó trông giống như một bảng, nhưng không có các tế bào có thể chỉnh sửa theo mặc định, và nó có thể phù hợp với dữ liệu của bạn Tốt hơn ở đây.

Bây giờ cho truy vấn, bạn có thể muốn đặt một truy vấn đơn lẻ để tránh lặp qua các kết quả và phải thực hiện thêm một truy vấn cho mỗi người dùng. Một cái gì đó như:

query = session.query(User.firstname, User.lastname, Address.address).filter(Address.user_id == User.id) 
    for row in query.all(): 
     # firstname, lastname, address = row 
     rows.append(row) 

Đối với rất nhiều hàng, tôi nghĩ rằng đó là một giải pháp, nhưng sau đó bạn sẽ cần phải xác định mô hình của riêng bạn và sử dụng LIMIT s trong các truy vấn của bạn. Với việc thiếu tài liệu và hướng dẫn, nó không phải là dễ dàng ...

Và như một lưu ý phụ, bạn không cần phải xác định phương pháp __init__ trên các lớp Địa chỉ và Người dùng, vì bạn không làm bất cứ điều gì đặc biệt , SQLAlchemy có thể làm điều này tự động cho bạn. Và bạn có thể xác định giá trị mặc định thẳng vào định nghĩa Cột.

CẬP NHẬT: ví dụ sử dụng QTableWidgetItem.setData, giả sử chúng tôi muốn xóa người dùng khi nhấp đúp. Chúng tôi sẽ sử dụng tín hiệu itemDoubleClicked.

# in the __init__ function 
self.table.itemDoubleClicked.connect(self.onItemDoubleClick) 

# in onItemDoubleClicked function 
def onItemDoubleClicked(self, item): 
    # Every data has a role, you can specify your own (it's an integer) as long as it's greater than UserRole. Others are used internally, like DisplayRole and some others you can find in the QtCore package. 
    # You can use data with other widgets also, not just TableWidgets. 
    user = item.data(QtCore.Qt.UserRole+1) 
    # you get a session however you want, then delete the user. This object is the same as the one you passed earlier when creating the item, it can be whatever you like. 
    session.delete(user) 
    session.commit() 
+0

Có vẻ ổn. Muộn của nó nên không thể thử nó ngay bây giờ. Bạn có thể vui lòng giải thích table_item.setData (QtCore.Qt.UserRole + 1, người dùng) – jbbiomed

+0

Điều này được sử dụng để bạn có thể thực sự thao tác đối tượng User, và không chỉ hiển thị tên của mình ... (ví dụ). Tôi sẽ cập nhật câu trả lời của mình để hiển thị một ví dụ. – jadkik94

+0

cảm ơn bạn vì đã giải thích. Tôi đoán bạn chỉ là ngắn gọn trong mã đầu tiên bạn đăng và tôi có thể dễ dàng thêm một tham chiếu đến đúng người dùng ở đúng nơi và không có phép thuật mà bạn đang sử dụng. – jbbiomed

Các vấn đề liên quan