Django的单例体系结构是否使其无法作为库中的独立ORM使用? [英] Does Django's singleton architecture make it unworkable as a standalone ORM in a library?

查看:60
本文介绍了Django的单例体系结构是否使其无法作为库中的独立ORM使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢Django ORM。它简单,易用且功能强大。

I like the Django ORM. It's simple, easy to use, and reasonably powerful.

我目前正在为我工​​作的VFX公司开发一些内部站点,为此我使用了Django。同时,我们正在开发其他python应用程序和库,以在生产中的各种上下文中使用。在很多地方,我们的核心库都需要与某些数据库进行交互,使用像Django这样的ORM确实会有所帮助。我知道其他选项,例如SqlAlchemy或PeeWee,但是我想看看Django是否可以工作,因为我在网站上使用了它,并且我更喜欢它的API。

I'm currently developing some internal sites for the VFX company I work for, for which I've used Django. In the meantime, we are developing other python applications and libraries to be used in various contexts in production. There's a number of places in which our core library needs to be interacting with some databases, and using an ORM like Django would really help things. I'm aware of other options like SqlAlchemy or PeeWee, but I'd like to see if Django will work since I use it on the websites and I like its API better.

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

Using Django as an ORM in a library is tricky (as I explored in a previous question), because Django expects to be used as a website with "apps". In a library, I might want to define any number of data models, which would exist in appropriate places in the library but not inside any Django app (as we're not using any other parts of the framework). So far so good.

我可以在库中的任何位置为我的模型创建基类,如下所示:

I can create a baseclass for my models anywhere in the library as follows:

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__

然后在库中的任何地方都可以创建自己的模型这个基类。由于我不依赖数据库名称的 app,因此需要明确声明它们。

Then anywhere in the library I can create my own models with this baseclass. Since I'm not relying on the "app" for the database names, I need to state them explicitly.

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

这避免了我不得不模拟应用程序结构的担忧。基类中的 name 属性为Django提供了所需的一切,然后Django不再抱怨找不到应用程序。其他模型文件可以放置在所需的任何位置。

This gets around my concern of having to simulate the structure of an "app". The name property in the base class supplies Django with all it needs, and then Django quits whining about not finding an app. The other model files can live wherever they want.

但是,有一个引人注目的用例,它们全部消失了。假设我的Django Web应用程序要使用公司核心python库中的某些功能,该库现在将Django ORM用于各种用途。由于我在库中调用了django.conf.settings.configure,因此Django在尝试运行主应用程序时会大声疾呼地定义设置。

However, there is a glaring use case where this all falls apart. Say that my Django web application wants to use some functionality from the company core python library, which now uses the Django ORM for various things. Since I make a call to django.conf.settings.configure in the library, Django is going to scream about defining the settings more than once when it tries to run the main application.

因此,基本上,使用Django ORM的库与Django不兼容。很棒。

有什么解决办法吗?我的意思是,这是一个可爱的ORM-真的不可能以独立的模块化方式使用吗? Django体系结构在本质上是完全单例的,从而使这不可能吗?

Is there any way around this? I mean, it's a lovely ORM - is it really this impossible to use in a standalone modular way? Is the Django architecture utterly singleton in nature, making this impossible?

*非重复
我正在尝试建立一个使用Django作为ORM的公司python库。可能依赖它的某些东西可能是Django网站本身。如何避免Django仅设置设置一次的单例坚持?还是可能吗? 这些答案都不能解决这个问题!

推荐答案

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

A simple answer is how to initialize Django in a standalone application and do it compatible with Django applications.

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()有周期性依赖的风险如果在另一个相似的代码启动的setup()内部调用一个代码,或者由manage启动的常规Django项目,则可以调用该代码。它类似于 manage.py ,其中 django.setup()在内部也被调用。 execute_from_command_line(sys.argv)。安装程序将初始化与INSTALLED_APPS相关的所有模块,所有urls模块以及所有所有的视图等。它们中的许多都是惰性的,但仍然是惰性的。如果setup()调用的任何代码都依赖于此,则 not apps.ready 的条件都不起作用。 setup()不可重入,并且启动失败。)

This is more compatible with Django then the answer by Oleg Russkin (where a risk of cyclic dependency at django.setup() is possible if the code is called inside inside a setup() initiated by another similar code or a normal Django project started by manage. It is similar to manage.py where django.setup() is also called internally by execute_from_command_line(sys.argv). The setup initializes all modules related to INSTALLED_APPS all urls modules and consequently all views etc. Many of them are lazy, but still. If any code called by setup() depends on this then neither the condition not apps.ready doesn't help. The setup() is not reentrant and the startup fails.)

更一般的答案

Django的一个重要概念是支持编写可重用的代码部分(Django术语中的应用程序,可以独立开发和测试)也可以有依赖关系树,但是如果可能的话,应该避免不受控制的相互依赖)可重用的应用程序应该可以更容易地组合到整个项目中(Django术语中的项目具有通过Python运行它的所有必要设置) 。)

An important concept of Django is to support writing reusable parts of code ("applications" in Django terminology, that can be developed and tested independently. There can be also a tree of dependencies, but uncontrolled mutual dependencies should be avoided if possible) Reusable applications are expected that they can be easier combined to whole project ("project" in Django terminology is with all settings necessary to run it by Python.)

Django ORM中唯一无法避免且有用的单例是数据库连接 django.db.connections django.conf.settings ,尤其是 INSTALLED_APPS 。来自同一进程或线程的同一数据库只应使用一个连接。

The only unavoidable and useful "singleton" in Django ORM are database connections django.db.connections and django.conf.settings especially INSTALLED_APPS. Only one connection should be used to the same database from the same process or thread.

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

Django is very configurable. An extreme example: It is possible to write a single file project where all code like settings, models, URL configs and views is defined in one file. That extreme that is probably useful only for some special tests or very short demos or as an exercise. It is even possible to define a project by one file with two "reusable" applications :-)

Django也支持 旧版数据库,其中数据库结构与现有的非Django应用程序共享,并且可以通过inspectdb命令创建模型。此类模型中的表名是显式的,不包含应用程序名称。另一方面,应用程序名称前缀对于防止来自独立应用程序的相同表名可能发生冲突很有用。一个重要的决定是可以将其用作旧版数据库还是普通的Django数据库。

Django supports also "legacy databases" where the database structure is shared with existing non Django applications and models can be created by inspectdb command. Table names in such models are explicit and don't contain the app name. On the other hand the app name prefix is useful to prevent a possible conflict of the same table names from independent "applications". An important decision is if you can use it as a "legacy" database or a normal Django database.

您可以在以下两个解决方案之间进行选择或合并它们:

You can decide between following two solutions or to combine them:


  • 使用例如 foo_models bar.models 并从中导入所有模型,例如到 app.models 并将仅 app 添加到 INSTALLED_APPLICATIONS 。如果只有一家公司,而没有其他公司,并且可以进行中央名称分配,那么这可能是可行的。 (最简单,但天真)

  • 对多个应用程序使用命名空间的粗略分隔。您应该使用不超过一个带有简单名称且没有应用名称前缀的应用。

  • Use e.g. foo_models or bar.models and import all models from them e.g. to app.models and add only that "app" to INSTALLED_APPLICATIONS. This can be viable if it is only for one company and never otherwise and central name assigment is possible. (easiest but little naive)
  • Use some coarse separation of namespaces to several apps. You should probably use not more than one app with simple names without app name prefix.

请提前考虑迁移 **。如果您以后为同一数据库和数据库表的不同子集创建更多项目,而又不将它们分离到更多应用程序且没有应用程序名称空间,它们可能会非常复杂,并且很快将变得不可能。

Think ahead about migrations**. They will be probably very complicated and very soon impossible if you will create later more projects for the same database and different subsets of database tables without separating them to more apps and without app namespace.

除了 django.db.connections 本身以外,Django ORM中确实没有单个 。如果使用更多的数据库,则可以通过 DATABASE_ROUTERS 将某些表定向到特定的数据库,即使使用相同表名且没有前缀的两个不同模型也是如此。

There is really no "singleton" in Django ORM except of django.db.connections itself. If you use more databases you can direct some tables to a specific database by DATABASE_ROUTERS, even with two different models that use the same table name without a prefix.

这篇关于Django的单例体系结构是否使其无法作为库中的独立ORM使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆