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

问题描述 投票:45回答:5

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

澄清

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

python django in-memory-database django-syncdb
5个回答
78
投票

所有Django管理命令can be accessed programmatically

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

理想情况下,你会在runserver上使用pre-init信号来激活它,但这样的信号是doesn't exist。所以,实际上,如果我是你,我将处理这个问题的方法是创建一个自定义管理命令,如runserver_newdb,并在其中执行:

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

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


9
投票

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

例如(未经测试):

startup.朋友:

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
 )

5
投票

更新

我在项目的根目录中添加了一个名为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脚本轻松完成此操作。我认为没有任何理由在syncdb内放置(或调用)settings.py

你能在问题中添加更多细节吗?添加上下文并解释您到底想要完成的内容?


0
投票

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

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

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

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

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


0
投票

@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...'])
© www.soinside.com 2019 - 2024. All rights reserved.