首页 > 解决方案 > 如何处理 Peewee 模型和应用程序控制器之间的交叉引用?

问题描述

在使用 Peewee 进行编码时,我想利用面向对象的编程风格。不幸的是,文档只给出了处理数据库连接的全局变量的提示。当我尝试利用 Model 和 Controller 对象(此时 View 并不重要)时,我遇到了错误,可能是因为相互交叉引用:

ImportError:无法从“应用程序”导入名称“应用程序”(C:\ [... src ...])

Peewee 要求将数据库处理程序放在抽象类定义中,如下所示:

class BaseModel(Model):
    class Meta:
        database = SqliteDatabase('../res/db.db', pragmas={'foreign_keys': 1})

好吧,问题是,我不能保持这样的 DB 处理程序。我正在为带有服务模块的独立 Windows 应用程序准备我的应用程序。出于这个原因,我想我需要在配置文件中存储 db 文件的绝对路径。因此,在模型开始加载数据库之前,我需要从控制器加载配置文件。

我所做的是将数据库处理程序推送到控制器中的静态字段:

from Application import Application
from peewee import *

class BaseModel(Model):
    class Meta:
        database = Application.database

如您所见,数据库处理程序取自Application抽象控制器。Application是一个基本控制器,从中派生GuiAppServiceApp。两个后代都使用相同的数据库,因此将处理程序保留为静态字段对我来说看起来很方便。

现在,请看一下我的应用程序类:

import logging.handlers
from peewee import SqliteDatabase
import datetime
import threading
from Windows import *

class Application:

    database = SqliteDatabase(None)

    def __init__(self, appname):
        # (...)

        from Entities import RouterSettings, BalanceEntry

         Application.database.init(
        conig_app_src + 'db.db',
        pragmas={'foreign_keys': 1})
        Application.database.connect()
        # !!!
        from Entities import RouterSettings, BalanceEntry 
        # !!!
        Application.database.create_tables([RouterSettings, BalanceEntry], safe=True)

问题是,当我将 Peewee 实体导入放在我开始使用它们的地方之前,我的意思是,在__init__方法内部,我不知何故失去了应用程序其他部分的可访问性。它迫使我将这个导入语句放在每个控制器方法中,以便正确访问实体模型。

另一方面,当我将实体导入放在控制器模块之上时,我从交叉引用中得到错误。我在上面放的错误消息。

总而言之,我正在寻找使用 peewee 模型管理应用程序的 OOP 方式。你知道有什么办法吗?还是我必须在应用程序初始化中使用全局数据库变量?

标签: pythonooppeewee

解决方案


感谢@coleifer,我决定为数据库处理创建另一个类:

class DbHandler:
    database = SqliteDatabase(None)

    @staticmethod
    def start(dbSrc):
        DbHandler.database.init(
            dbSrc + '\\res\\SIMail.db',
            pragmas={'foreign_keys': 1})
        DbHandler.database.connect()
        DbHandler.database.create_tables([RouterSettings, BalanceEntry],
                                         safe=True)

好吧,最终它看起来与全局变量非常相似,但我认为这个解决方案符合我的需求。最重要的是,我设法摆脱了交叉引用。


推荐阅读