Взаимодействие между модулями / классами в wxPython

У меня есть задача по переносу многопользовательского проекта VBA с большим количеством взаимодействий с базами данных во что-то другое - поскольку это должно быть чем-то, что не может требовать установки программного обеспечения (поэтому JRE и.NET исключены). Я считаю, что это можно сделать с Python - wxPython покрывает фреймы и различные элементы управления (я использую boa-конструктор для его конструктора фреймов), мне также удалось подключиться через adodbapi к текущей базе данных, используемой VBA. Я просто отстой в том, чтобы все сложить правильно. Рассмотрим этот скелет:

myApp.py

#!/usr/bin/env python
#Boa:App:BoaApp

import wx
import myFrame

modules ={u'myFrame': [1, 'Main frame of Application', u'myFrame.py']}

class BoaApp(wx.App):
    def OnInit(self):
        # here I think I'd see something like, say:
        # self.main.cnnObject = adodbapi.connect ( some proper connection string )
        self.main = myFrame.create(None)
        self.main.Show()
        self.SetTopWindow(self.main)
        return True

def main():
    application = BoaApp(0)
    application.MainLoop()

if __name__ == '__main__':
    main()

myFrame.py

#Boa:Frame:myFrame
import wx

def create(parent):
    return myFrame(parent)

[wxID_MYFRAME, wxID_MYFRAMEBUTTON1, 
] = [wx.NewId() for _init_ctrls in range(2)]

class myFrame(wx.Frame):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_MYFRAME, name='myFrame', parent=prnt,
              pos=wx.Point(710, 329), size=wx.Size(400, 250),
              style=wx.DEFAULT_FRAME_STYLE, title='MainFrame')
        self.SetClientSize(wx.Size(392, 223))

        self.button1 = wx.Button(id=wxID_MYFRAMEBUTTON1,
              label='FETCH cnnObject', name='button1', parent=self,
              pos=wx.Point(0, 144), size=wx.Size(392, 79), style=0)
        self.button1.Bind(wx.EVT_BUTTON, self.OnButton1,
              id=wxID_MYFRAMEBUTTON1)

    def __init__(self, parent):
        self._init_ctrls(parent)

    def OnButton1(self, event):
        event.Skip()
        # here and in other events in other frames I would like to retrieve 
        # that cnnObject to use for queries

Добавление множества элементов управления, событий, открытие последовательных фреймов из этого и следующего, похоже, работает. Однако, чтобы не приходилось копировать / вставлять все содержимое соединения с базой данных снова и снова, я хотел, чтобы все было в одном месте и просто получал доступ к этому коду из фреймов. Моя общая идея состоит в том, что, поскольку существует только один объект myApp, он может содержать объект подключения, тем более что строка подключения будет доступна как sys.argv[1]. Возможно ли это? И если да, то как бы я сослался на объект приложения внутри метода OnButton1? Также есть шанс, что я все понял неправильно, и в этом случае я хотел бы услышать схему "правильного пути". Я чувствую, что мне может не хватать, возможно, подходящей оболочки класса для этих операций с базой данных, но даже если я ее сделаю, мне все равно хотелось бы иметь только один экземпляр этого класса во всех моих будущих фреймах, но я не могу даже удается сделать это с помощью экземпляра приложения - я импортирую myApp в myFrame (что само по себе кажется странным, поскольку myApp уже импортирует myFrame, так что в обоих направлениях?), но независимо от того, какой тип присвоения локальной переменной я пытаюсь, я в основном получаю " у объекта 'module' нет атрибута " ... (что заставляет меня думать, что я, вероятно, не понимаю, как работают области видимости / модули в Python)

1 ответ

Я написал немного об этом, но я использовал SQLAlchemy. Это была моя первая попытка:

Затем я получил комментарии и помощь от друга из сообщества wxPython и разработчиков SQLAlchemy и немного обновил приложение:

Эта вторая статья показывает, как создать сеанс базы данных и передать его. Я думаю, что это подход, который вы ищете. Я бы сделал подключение к базе данных в методе init вашего фрейма верхнего уровня:

def __init__(self):
    """Constructor"""
    wx.Frame.__init__(self, None, title="Databases!")

    self.data_connection = self.create_connection()

Затем, когда вы создаете другие кадры, вы можете передать им это соединение:

def create_new_frame(self):
    """"""
    new_frame = MyOtherFrame(self.data_connection)
    new_frame.Show()

Вот один из способов, которым вы можете настроить класс фреймов:

########################################################################
class MyOtherFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, data_connection):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Other frame")
        self.data_connection = data_connection

Просто убедитесь, что вы не закрываете соединение для передачи данных в другом кадре, поскольку это также закроет его в исходном кадре верхнего уровня.

Это решение также относится к вашему вызову OnButton1. Просто измените это так:

def OnButton1(self, event):
    cursor = self.data_connection.cursor()

Вы заметите, что вы можете получить доступ к self.data_connection в любом месте вашего основного фрейма, потому что он был определен как переменная уровня класса.

Вы также можете быть заинтересованы в проекте Dabo, который является оболочкой для wxPython, которая должна облегчить работу с базами данных: http://www.dabodev.com/

Другие вопросы по тегам