Here is an example of two database entities which share a one-to-one relationship. This example uses alternateID's in the user interface. This example uses SQLObject r865, pysqlite 2.0.2, and gazpacho 0.5.3 db_schema.py:: #!/usr/bin/python from sqlobject import * import os conn = connectionForURI("sqlite://" + os.getcwd() + "/database.db") class Person(SQLObject): _connection = conn # attributes name = StringCol(notNone=True, alternateID=True) # relationships toaster = SingleJoin('Toaster') # Person has one Toaster class Toaster(SQLObject): _connection = conn # attributes color = StringCol(notNone=True, alternateID=True) # relationship person = ForeignKey('Person') # Person has one Toaster initialize_db.py:: #!/usr/bin/python from db_schema import * Person.createTable() Toaster.createTable() Person(name="john") Person(name="bob") Toaster(color="blue",person=None) Toaster(color="green",person=None) person.py:: #!/usr/bin/python import pygtk pygtk.require('2.0') import gtk from gazpacho.loader.proxy import Proxy from db_schema import * from gtk_util import * class PersonEditor(Proxy): def __init__(self,person_id): Proxy.__init__(self, gladefile="person.glade") # connect to db self.person = Person.get(person_id) # name entry if self.person.name != None: self.name_entry.set_text(self.person.name) # toaster combo toaster_list = [toaster.color for toaster in Toaster.select()] combo_fill_text(self.toaster_combo, toaster_list) if self.person.toaster != None: combo_set_from_db(self.toaster_combo, self.person.toaster.color) def on_window1__destroy(self, window): gtk.main_quit() def on_name_entry__changed(self,widget): self.person.name = widget.get_text() def on_toaster_combo__changed(self, widget): if self.person.toaster != None: self.person.toaster.person = None toaster_color = combo_get_value(widget) toaster = Toaster.byColor(toaster_color) toaster.person = self.person.id if __name__ == "__main__": import sys assert len(sys.argv) >= 2 person_id = int(sys.argv[1]) app = PersonEditor(person_id) gtk.main() person.glade:: True Person 0.0 True 2 2 True True 1 2 1 2 toaster True 2 1 True True 1 2 name True toaster.py:: #!/usr/bin/python import pygtk pygtk.require('2.0') import gtk from gazpacho.loader.proxy import Proxy from db_schema import * from gtk_util import * class ToasterEditor(Proxy): def __init__(self,toaster_id): Proxy.__init__(self, gladefile="toaster.glade") # connect to db self.toaster = Toaster.get(toaster_id) # color entry if self.toaster.color != None: self.color_entry.set_text(self.toaster.color) # person combo person_list = [person.name for person in Person.select()] combo_fill_text(self.person_combo, person_list) if self.toaster.person != None: combo_set_from_db(self.person_combo, self.toaster.person.name) def on_window1__destroy(self, window): gtk.main_quit() def on_color_entry__changed(self,widget): self.toaster.color = widget.get_text() def on_person_combo__changed(self, widget): person_name = combo_get_value(widget) person = Person.byName(person_name) if person.toaster != None: person.toaster.personID = None self.toaster.personID = person.id if __name__ == "__main__": import sys assert len(sys.argv) >= 2 toaster_id = int(sys.argv[1]) app = ToasterEditor(toaster_id) gtk.main() toaster.glade:: True Toaster 0.0 True 2 2 True True 1 2 1 2 True 1 2 person True 2 1 color True gtk_util.py:: import gtk def combo_fill_text(combo_widget, content_list): liststore = gtk.ListStore(str) combo_widget.set_model(liststore) cell = gtk.CellRendererText() combo_widget.pack_start(cell, True) combo_widget.add_attribute(cell, 'text', 0) for item in content_list: combo_widget.append_text(item) def combo_set_from_db(combo_widget, db_item): list_model = combo_widget.get_model() iter = list_model.get_iter_first() while list_model.get_value(iter,0) != db_item: iter = list_model.iter_next(iter) combo_widget.set_active_iter(iter) def combo_get_value(widget): list_model = widget.get_model() iter = widget.get_active_iter() return list_model.get_value(iter,0)