在 django 中,如何从初始化脚本中调用子命令“syncdb”?

Posted

技术标签:

【中文标题】在 django 中,如何从初始化脚本中调用子命令“syncdb”?【英文标题】:In django, how do I call the subcommand 'syncdb' from the initialization script? 【发布时间】:2011-03-30 14:03:44 【问题描述】:

我是 python 和 django 的新手,在关注 Django Book 时,我了解了为我生成数据库表的命令“python manage.py syncdb”。在开发环境中,我在内存数据库中使用 sqlite,所以每次我重新启动服务器时它都会自动删除。那么如何编写这个“syncdb”命令的脚本呢?(应该在“settings.py”文件中完成吗?)

澄清

OP 正在使用内存数据库,该数据库需要在使用针对该数据库定义的 Django 模型的任何进程开始时进行初始化。确保数据库初始化(每个进程启动一次)的最佳方法是什么。这将用于通过manage.py runserver 或通过网络服务器进程(例如使用 WSGI 或 mod_python)运行测试或运行服务器。

【问题讨论】:

【参考方案1】:

所有 Django 管理命令can be accessed programmatically:

from django.core.management import call_command
call_command('syncdb', interactive=True)

理想情况下,您应该在 runserver 上使用预初始化信号来激活它,但这样的信号 doesn't exist。所以,实际上,如果我是你,我的处理方式是创建一个自定义管理命令,如 runserver_newdb,并在其中执行:

from django.core.management import call_command
call_command('syncdb', interactive=True)
call_command('runserver')

有关编写自定义管理命令的更多信息,请参阅the documentation。

【讨论】:

您会将“from django.core.management import call_command call_command('syncdb', interactive=True)”放在哪个文件中(在典型的 django 项目中)? @EdwardD'Souza:对于这个用例,我会将其放入settings.py 或从settings.py 导入的脚本中【参考方案2】:

正如“Where to put Django startup code?”所建议的,您可以将中间件用于您的启动代码。 Django 文档是here。

例如(未经测试):

startup.py:

from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
from django.core.management import call_command

class StartupMiddleware(object):
    def __init__(self):
        # The following db settings name is django 1.2.  django < 1.2 will use settings.DATABASE_NAME
        if settings.DATABASES['default']['NAME'] == ':memory:':
            call_command('syncdb', interactive=False)

        raise MiddlewareNotUsed('Startup complete')

在你的 settings.py 中:

 MIDDLEWARE_CLASSES = (
     'your_project.middleware.startup.StartupMiddleware',

     # Existing middleware classes here
 )

【讨论】:

【参考方案3】:

更新

我在项目的根目录中添加了一个名为run.sh 的脚本。这适用于我的 SQLite 数据库:

#!/usr/bin/python
from django.core.management import call_command
call_command('syncdb')
call_command('runserver')

原答案

我不确定我是否理解您所说的“编写 syncdb 命令脚本”是什么意思。您通常从命令行执行python manage.py syncdb。这通常在添加新模型后完成。如果您希望使用简单的 shell 脚本轻松完成此操作。我看不出有任何理由在 settings.py 中放置(或调用)syncdb

您能否为您的问题添加更多详细信息?添加上下文并解释您到底想要完成什么?

【讨论】:

我希望像任何其他python方法一样调用这个'syncdb'命令,并将调用放在settings.py中,所以每次我启动应用程序时它都会自动创建数据库 知道了。我不相信settings.py 是保存它的最佳位置。我们可以同意不同意:) 您还有什么建议吗?我对python完全陌生。正如 Craig Trader 所说,“syncdb”的调用必须发生在同一个进程中,所以我想这让 shell 脚本毫无疑问。 找到了通过API调用syncdb的机制。更新了答案。关于放置它的位置还没有更好的想法:( 自从丹尼尔回答了第一个学分归他所有,但无论如何 +1 为您的帮助,谢谢。【参考方案4】:

您可以创建一个您调用的新脚本,而不是调用 manage.py 的 manage.py:

from subprocess import call
call(["python", "manage.py", "syncdb"])
call(["python", "manage.py", "runserver"])

如果您不需要添加管理员,您可以像这样更改第二行:

call(["python", "manage.py", "syncdb", "--noinput"])

我假设您要做的是创建您的数据库,然后每次使用一个命令启动您的服务器。

【讨论】:

我希望以某种 python API 的形式访问“syncdb”,但没关系。 这可能不适用于内存数据库,因为每个 call 都在调用一个单独的进程,该进程将拥有自己的内存数据库。 是的,你是对的。这可能会让 bash 脚本毫无疑问。【参考方案5】:

@Daniel Naab 的回答,以及官方网站中的文档,不是用于执行管理命令作为入口点。

如果您想在 AWS Lambda 或 Google Cloud Functions 等托管云环境中使用管理命令作为入口点,您可以查看 manage.py 并尝试类似的方法。

import os
from django.core.management import execute_from_command_line

def publishing_fn(data, context):
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'YOURAPP.settings')
    # The first argument is "manage.py" when it's run from CLI.
    # It can be an empty string in this case
    execute_from_command_line(['', 'COMMAND', 'ARGS...'])

【讨论】:

以上是关于在 django 中,如何从初始化脚本中调用子命令“syncdb”?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Views.py 中运行子进程——Django

如何在C语言中调用cmd命令?

如何在C语言中执行shell命令

如何在C语言中调用shell命令

如何在C语言中调用shell命令

在单个命令行中多次调用同一子命令