Django 的单例架构是否使其无法作为库中的独立 ORM 工作?



我喜欢django orm。它很简单,易于使用且功能合理。

我目前正在为我工作的VFX公司开发一些内部站点,为此我使用了Django。同时,我们正在开发其他Python应用程序和库,这些应用程序和库将在生产中的各种情况下使用。我们的核心库需要在许多地方与某些数据库进行交互,并且使用django这样的ORM确实会对事情有所帮助。我知道Sqlalchemy或Peewee等其他选项,但是我想看看Django是否会起作用,因为我在网站上使用它,并且更喜欢它的API。

将Django用作库中的ORM很棘手(正如我在上一个问题中探讨的那样),因为Django希望将其用作带有"应用程序"的网站。在库中,我可能想定义任何数量的数据模型,这些数据模型将存在于库中的适当位置,而不是在任何Django应用程序中都存在(因为我们不使用框架的任何其他部分)。到目前为止,一切都很好。

我可以在库中的任何地方为我的模型创建一个基本,如下所示:

from django.db import models
from django.apps import apps
import django.conf
django.conf_settings.configure(
    DATABASES = ...
)
apps.populate((__name__,))
class LibModel(models.Model):
    class Meta:
        abstract = True
        app_label = __name__

然后在库中的任何地方,我都可以使用此基座创建自己的模型。由于我不依赖"应用程序"来数据库名称,因此我需要明确陈述它们。

class SpecificModel(LibModel):
    # fields go here
    class Meta(LibModel.Meta):
        db_table = "specific_model_table_name"

这使我担心必须模拟"应用程序"的结构。基类中的名称属性提供了所有需要的Django,然后Django退出了关于找不到应用程序的抱怨。其他模型文件可以在任何需要的地方生活。

但是,有一个明显的用例,所有这些都崩溃了。假设我的Django Web应用程序希望使用公司Core Python库中的一些功能,该库现在使用Django Orm进行各种功能。由于我在库中拨打Django.conf.settings.configure,因此Django会在尝试运行主应用程序时尖叫有关定义设置以上一次的尖叫。

基本上,使用Django Orm的库与Django不相容。很棒。

有什么方法可以解决吗?我的意思是,这是一个可爱的ORM-真的不可能以独立的模块化方式使用吗?Django建筑本质上是完全单身人士,这使得这不可能吗?

*不是重复的我正在尝试拥有一个使用Django作为ORM的公司Python库。可能取决于它的某些事情可能是Django网站本身。如何仅在设置设置配置时坚持Django的Singleton坚持?还是可能?这些答案都没有解决此问题!

您可以检查是否已经配置了Django。

from django.apps import apps
from django.conf import settings
if not apps.ready:
    settings.configure()
    django.setup()

启动Django应用程序时 - 可以将Core Python库配置为单独的应用程序。

另外,请在运行时检查动态应用程序加载的答案。

一个简单的答案是如何在独立应用程序中初始化django并与django应用程序兼容。

import os
import django
if not 'DJANGO_SETTINGS_MODULE' in os.environ:
    os.environ['DJANGO_SETTINGS_MODULE'] = 'mysettings'
    # # or without DJANGO_SETTINGS_MODULE directly
    # from django.conf import settings
    # settings.configure(DATABASES=... other...)
    django.setup()
# this shouldn't be before DJANGO_SETTINGS_MODULE or settings.configure(...)
from myapp.models import MyModel
# this shouldn't be called before django.setup()
queryset = MyModel.objects.filter(...)

这与django更兼容,而不是oleg russkin的答案(如果由另一个类似代码或由另一个类似代码启动的设置或一个正常的django项目启动的setup()内部的代码在 django.setup()处有循环依赖性的风险。它类似于 manage.py,其中 django.setup()也由 execute_from_command_line(sys.argv)内部调用。设置初始化了与已安装_App相关的所有模块所有URL模块,因此所有视图等。其中许多都很懒惰,但仍然。如果有任何代码。因此,条件 not apps.ready均无济于事。设置()不是重新进入,而启动失败。)


更多一般答案

django的一个重要概念是支持写作可重复使用代码的部分(django术语中的"应用程序",可以独立开发和测试。如果可能的话,应避免相互依赖性)可重复使用的应用程序,可以预期它们可以更容易地结合到整个项目(django术语中的"项目"都与Python运行所需的所有设置。)

django orm中唯一不可避免且有用的"单例"是数据库 Connections django.db.connectionsdjango.conf.settings,尤其是CC_7。从同一过程或线程中只能将一个连接用于同一数据库。

django非常配置。一个极端的例子:可以编写一个单个文件项目,其中所有代码(例如设置,模型,URL配置和视图)都在一个文件中定义。这种极端可能仅对某些特殊测试或非常短的演示或练习有用。甚至可以通过一个文件来定义一个通过两个"可重复使用"应用程序来定义一个项目: - )

django也支持" logacy 数据库",其中数据库结构与现有的非Django应用程序共享,并且可以由InspectDB命令创建模型。此类模型中的表名是显式的,并且不包含应用程序名称。另一方面,应用程序名称前缀可用于防止独立"应用程序"中同一表名称的可能冲突。一个重要的决定是,您是否可以将其用作"遗产"数据库或普通Django数据库。

您可以在以下两个解决方案之间决定或组合它们:

  • 使用,例如foo_modelsbar.models并从中导入所有模型,例如到app.models,仅将"app"添加到INSTALLED_APPLICATIONS。如果仅适用于一家公司,并且不可行,并且可以使用中央名称,则这可能是可行的。(最简单但小天真)
  • 将命名空间的一些粗略分开到几个应用程序。您可能应该使用不超过一个具有不含应用程序前缀的简单名称的应用程序。

考虑迁移**。它们可能非常复杂,很快您将稍后为同一数据库和数据库表的不同子集创建更多项目,而无需将它们分开到更多的应用程序,而没有应用程序空间。

除了 django.db.connections本身外,django orm中确实有没有" singleton" 。如果您使用更多数据库,则可以通过DATABASE_ROUTERS将某些表引导到特定数据库,即使使用两个不同的模型使用相同的表名称,而没有前缀。

最新更新