2012-05-16 18 views
6

私の質問は、PySideのQTableViewクラスからアクセスできるSQLAlchemy宣言型モデルを実際にセットアップする方法です。私は基本的にObject Relational tutorialPySide + SQLAlchemyのQTableView用の「モデル」の設計。

のフロントエンドを実装しようとしている

残念ながら、私は混乱のいくつかのポイントがあります。私はどこにいるのか説明しようとします。

SQLAlchemyのチュートリアルでは、関連する2つのテーブルがあり、問題のないテーブルを操作/照会できます。確かにQTableView classを確立しようとすると、私自身のモデルでsetData() methodが必要です。または、デフォルトモデルを使用するにはsetItem() methodが必要です。

ですから、モデルをどのように設計するのかという疑問があります。私は、データベースを照会/変更するための2つの方法の1つを定義することを意味します。私はこれを行う正しい方法を知らない。

モデルは、すべてのアドレスが表示されるまで少数の行で繰り返されるUser firstnameとlastnameのようになっていて、次のUserに移動します。これをプロンプトで印刷するためにネストされたforループでこれを行うことができますが、大きなリストを作成することが最初の場所にデータベースを持つ点を打ち負かすように見える方法だとは思わない...

また、データベースが大きくなり、テーブル全体がインスタンス化されてメモリに保持されたり、ユーザーがスクロールしたときに表示される行と列を読み込んだりしますか?

ここにテキストがたくさん残っていますが、明確にしようとしています。追加のものがあれば、私に知らせてください。または、私が間違ったトラックに完全に入っている場合....

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 

答えて

6

最初に、クエリを忘れて、使用しているループを使用してください。あなたがUIで探しているのは基本的なことです。私は文書の欠如から、QTableWidget(または何でもQWhateverWidget)を基本的なもののためにQWhateverViewよりよく使用することが最もよいことを発見しました。簡単なことのために独自のモデルを定義する必要はありません。ですから、QTableWidgetでそれを行う方法を説明します。 (行、列)に各セルのQTableWidgetItemを作成する必要があります。私が遭遇した1つの問題は、それらを追加する前に行の数を設定することでした。とにかく、ここで:

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_() 

あなたが使用して検討するかもしれないもう一つは、複数の列をサポートしていQTreeWidget、あり、そしてあなたはそれがデフォルトでテーブルのような、しかし、編集可能なセルなしに見えるようにすることができ、そしてそれはあなたのデータに合うかもしれませんここで良い。

クエリの場合は、結果をループしないように1つのクエリを作成し、各ユーザーに対して1つのクエリを追加する必要があります。ような何か:行の多くのために

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) 

は、私は解決策があると思いますが、あなたはあなた自身のモデルを定義して、クエリでLIMIT Sを使用する必要があります。ドキュメントとチュートリアルが不足しているので、それほど簡単ではありません。

そして、特別なことをしていないので、アドレスとユーザークラスに__init__メソッドを定義する必要はありません、SQLAlchemyはこれを自動的に行うことができます。また、デフォルト値を列定義に直接定義することもできます。

更新QTableWidgetItem.setDataを使用している例については、ダブルクリックしたときにユーザーを削除したいとします。 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

いいね。その遅れているので今すぐ試すことはできません。あなたは説明していただけますか?table_item.setData(QtCore.Qt.UserRole + 1、user) – jbbiomed

+0

これは実際にUserオブジェクトを操作できるように使用されています。私は例を示すために私の答えを更新します。 – jadkik94

+0

説明してくれてありがとう。私はあなたが投稿した最初のコードでは簡潔であることを前提としており、適切なユーザーへの参照を適切な場所に簡単に追加することができ、使用している魔法はありません。 – jbbiomed

関連する問題