【问题标题】:Django: Programmitically use 'inspectdb' during runtime on dynamic database connectionsDjango:在动态数据库连接上运行时以编程方式使用“inspectdb”
【发布时间】:2019-12-03 09:23:12
【问题描述】:

我有一个 Django 项目,其中每个用户组都有自己的数据库(“项目”)。每个项目都有一个条目,它保存在主数据库中。 Django 从主数据库读取所有当前项目并连接到他们的数据库。这就是为什么连接没有写在 settings.py 中的原因。动态连接到项目数据库的代码在根 urls.py 中运行,因为我从 stackoverflow 上的另一个线程中了解到,那里的代码在启动时运行一次。每当用户创建一个新项目时,一段代码都会创建一个新数据库并通过将连接附加到 settings.DATABASES 来连接到新数据库(参见下面的示例代码)。 触发了一个外部程序来用数据填充新数据库。

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

我尝试使用

解决上述问题
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 尝试了同样的事情,但仍然没有成功。

【问题讨论】:

    标签: python django database


    【解决方案1】:

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

    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附近接收结果文件。

    【讨论】:

      猜你喜欢
      • 2019-12-12
      • 2017-03-01
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 1970-01-01
      • 2012-02-29
      相关资源
      最近更新 更多