Django:在运行时以编程方式使用动态数据库连接'inspectdb'



我有一个Django项目,每个用户组都有自己的数据库("项目")。对于每个项目,都有一个条目,该条目保存在主数据库中。从主数据库 Django 读取所有当前项目并连接到它们的数据库。这就是为什么连接不是用 settings.py 写的。动态连接到项目数据库的代码段在根 urls.py 中运行,因为我从堆栈溢出的另一个线程中了解到那里的代码在启动时运行一次。每当用户创建新项目时,一段代码都会创建一个新数据库,并通过将连接附加到设置来连接到新数据库。数据库(请参阅下面的示例代码)。 触发外部程序以用数据填充新数据库。

现在的问题是我不能立即使用数据库,因为首先我需要运行 inspectdb 来获取 Django 的 ORM 结构。 我想在运行时执行此操作,因为必须关闭服务器并重新启动它意味着其他用户在此期间无法使用他们的项目。但即使手动使用命令行,Django 也会回答一个错误,即连接不存在。(我猜它试图在 settings.py 中找到连接?但是,对于我已经创建了ORM结构的项目,可以找到连接。所以我认为问题不在于将连接附加到设置的代码段。数据库。

我尝试使用

command = 'python manage.py inspectdb --database ' + name + ' > api_manager/schemas/' + name + '.py'
os.system(command)

但是,如上所述,它引发了连接不存在的异常。

在 settings.py 中,仅存在默认数据库:

DATABASES = {
'default': {
'ENGINE': engine,
'NAME': name,
'USER': user,
'PASSWORD': pwd,
'HOST': host,
'PORT': port
}
}

在根 urls.py 中:

...
from myproject.utils import connect_to_db
urlpatterns = [
...
]

# one time execution
for project in Project.objects.all():
connect_to_db(project.slug)

connect_to_db() 代码:

def connect_to_db(project):
settings.DATABASES[project] = {
'ENGINE': settings.engine,
'NAME': project,
'USER': settings.user,
'PASSWORD': settings.pwd,
'HOST': settings.host,
'PORT': settings.port
}
print("CONNECTED TO DATABASE: " + project)

项目创建:

def create_new_project(project_name):
slug = slugify(project_name).replace('-', '')
project_dir = os.path.join(settings.MEDIA_ROOT, "projects", slug)
try:
# Create entry in default database
project = Project()
project.name = project_name
project.slug = slug
project.save()
# Create new database
with connection.cursor() as cursor:
cursor.execute("CREATE DATABASE " + slug)
# Create projects folder in media
if not os.path.exists(project_dir):
os.mkdir(project_dir)
# create some other folders
else:
raise Exception("Project folder already exists!")
connect_to_db(slug)
return project
except:
raise

在外部程序运行后运行的代码段:

command = 'python manage.py inspectdb --database ' + name + ' > myapp/schemas/' + name + '.py'
os.system(command) # raises exception connection 'name' doesn't exist

我希望 Django 在运行时创建一个新的 ORM (models.py) 文件,以便我的用户可以立即使用新生成的数据库。

编辑:我用subprocess.run(...)而不是os.system尝试了同样的事情,但仍然没有成功。

我通过休息调用运行此代码:

from django.core.management import call_command
# base dir from your's project settings
from project_name.settings import BASE_DIR
import os 
with open(os.path.join(BASE_DIR, 'inspected.py'), 'w+') as f
call_command("inspectdb", stdout=f)

。并在 manage.py 附近接收结果文件。

最新更新