Lesson 3 : Different rows, one table¶
Download lesson [here]
In this lesson, we define two different column patterns (i.e. Row classes) than can be used in the same [document database] collection. As this is not an SQL database, rows in the same document (or “table”) do not have to conform to the same column pattern (or “schema”).
In the main Qt program, records in the database are presented as a Qt list, and on the right, a form with the details of the record are shown.
import sys
# from PyQt5 import QtWidgets, QtCore, QtGui # Qt5
from PySide2 import QtWidgets, QtCore, QtGui
from cute_mongo_forms.column import LineEditColumn
from cute_mongo_forms.row import ColumnSpec, Row
from cute_mongo_forms.container import List, FormSet
from cute_mongo_forms.db import SimpleCollection
Define a Row:
class PersonRow(Row):
columns=[
ColumnSpec(LineEditColumn, key_name="firstname", label_name="First Name"),
ColumnSpec(LineEditColumn, key_name="surname", label_name="Surname"),
ColumnSpec(LineEditColumn, key_name="address", label_name="Address")
]
Define another, slightly different Row:
class PersonRowExtended(Row):
columns=[
ColumnSpec(LineEditColumn, key_name="firstname", label_name="First Name"),
ColumnSpec(LineEditColumn, key_name="secondname",label_name="Second Name"),
ColumnSpec(LineEditColumn, key_name="surname", label_name="Surname"),
ColumnSpec(LineEditColumn, key_name="address", label_name="Address")
]
Create collection. SimpleCollection is a simple test database (just a python dictionary), but the interface to MongoDB works with the same API
collection=SimpleCollection(
filename="simple_test.db",
row_classes=[PersonRow,PersonRowExtended]
)
Next we create a list of database entries. The List class is Row agnostic. It only knows how to create a label, using a Row entry. The only method we need to overwrite is the one used to create a label:
class PersonList(List):
def makeLabel(self,entry):
try:
st=entry["firstname"]+" "+entry["surname"]
except KeyError:
st="?"
return st
The Qt program. The new part here is, that we instantiate a FormSet. It uses the collection to create forms for both PersonRow and PersonRowExtended and shows the active form, depending on what the user has chosen in PersonList.
There is also a demo on how to manipulate the database programmatically (outside the GUI)
class MyGui(QtWidgets.QMainWindow):
def __init__(self,parent=None):
super(MyGui, self).__init__()
self.initVars()
self.setupUi()
def initVars(self):
# Write a few entries to it
collection.new(PersonRow,{"firstname":"Paavo", "surname":"Vayrynen", "address":"Koukkusaarentie 1"} )
collection.new(PersonRow,{"firstname":"Martti", "surname":"Ahtisaari", "address":"Lokkisaarentie 1"} )
# Write some entries corresponding to the second row type as well
collection.new(PersonRowExtended,{"firstname":"Juho", "secondname":"Kustaa","surname":"Paasikivi", "address":"Kontulankaari 1"})
collection.new(PersonRowExtended,{"firstname":"Esko", "secondname":"Iiro", "surname":"Seppänen", "address":"Mellunraitti 3"} )
# Dump the database into the terminal
it=collection.get()
for i in it:
print(">>",i)
def setupUi(self):
self.setGeometry(QtCore.QRect(100,100,800,800))
self.w=QtWidgets.QWidget(self)
self.setCentralWidget(self.w)
self.lay=QtWidgets.QHBoxLayout(self.w)
# Create a list
self.lis=PersonList(collection=collection)
# Get lists's widget
self.lis.widget.setParent(self.w)
# Add to main layout
self.lay.addWidget(self.lis.widget)
# Create a group of forms
self.formset=FormSet(collection=collection)
# Get form's widget. It encapsulates the form widgets of each row type
self.formset.widget.setParent(self.w)
# Add formset to layout
self.lay.addWidget(self.formset.widget)
# Inform formset about the item in question
self.lis.widget.currentItemChanged.connect(self.formset.chooseForm_slot)
# self.findSome() # enable this for demonstrating the "manual" (i.e. outside the GUI) manipulation of the database
def findSome(self):
# In this example we use SimpleCollection (just a demo database). For MongoCollection, you would use pymongo syntax to perform queries.
# (1) Search all "PersonRowExtended" rows with their secondname being "Kustaa"
it=collection.get({"classname":"PersonRowExtended","secondname":"Kustaa"}) # Returns an iterator.
doc=next(it) # a python dictionary
# (2) Search all "PersonRowExtended" rows
it=collection.get({"classname":"PersonRowExtended"}) # Returns an iterator.
for doc in it:
print(doc) # python dictionary
# (3) Change values in the database programmatically and after that, update the fields in the widgets
doc["secondname"]="Kusti"
collection.update(PersonRowExtended,doc)
self.lis.update()
Start the main Qt program
if (__name__=="__main__"):
app=QtWidgets.QApplication([])
gui=MyGui()
gui.show()
app.exec_()