3

我的项目设置有以下方案:

myproject/
   app1/
   app2/
   appN/
   settings/
      __init__.py
      base.py
      devel.py
      production.py

在我的本地环境中,我在 virtualenvwrapper 的postactivate脚本中:

myproject_root=/home/rantanplan/Projects/repos/myproject
cd $myproject_root
export DJANGO_SETTINGS_MODULE=myproject.settings.devel

这样当我这样做workon myproject时,它将更改为项目的根目录并设置DJANGO_SETTINGS_MODULE我想要的活动。

这对 django 和所有命令(如python manage.py syncdb)都有效。

另一方面,现在我有这个织物任务:

@task
def syncdb():
    local('python manage.py syncdb --noinput')

当我有一个简单的settings.py文件时,这曾经可以正常工作,但是当我更改为上述方案时,它会引发此异常:

django.core.exceptions.ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.

Fatal error: local() encountered an error (return code 1) while executing 'python manage.py syncdb --noinput'

Aborting.

一些附加说明:

  • 项目功能在这里不适用,因为它错误地假设(内部)所有 django 设置模块都被命名为“设置”。
  • 我尝试了settings_module功能无济于事。它在os.environ内部使用来设置环境变量,但没有效果。
  • 如果我os.environ['DJANGO_SETTINGS_MODULE']在任务定义之前打印,它会正确打印“myproject.settings.devel”。

那么我在这里做错了什么,你建议我应该如何解决这个问题?


为了省去你的麻烦,我应该说我知道我可以通过以下方式解决这个问题:

def syncdb():
    with prefix('export DJANGO_SETTINGS_MODULE=myproject.settings.devel'):
        local('python manage.py syncdb --noinput')

但如果可以的话,我宁愿避免使用prefix

我也知道我可以做到,正如 hynekcer 建议的那样:

@task
def syncdb():
    local('python manage.py syncdb --settings=myproject.settings.devel --noinput')

但我真的很想知道为什么local不尊重DJANGO_SETTINGS_MODULE和为什么settings_module不像宣传的那样工作。

4

2 回答 2

1

您可以使用settings选项。它优先于 DJANGO_SETTINGS_MODULE 变量。

@task
def syncdb():
    local('python manage.py syncdb --settings=myproject.settings.devel --noinput')
于 2012-11-14T00:45:28.983 回答
1

好吧,我发现了问题,但我不知道该怎么做。

首先,我似乎没有透露所有必要的信息。

虽然我的 django 项目的结构与我描述的完全一样,但我的结构结构有点复杂。

本质上,我遵循织物文档的这一部分中的一些模式

完整的结构描述如下:

deployment/
  __init__.py
  fabric/
    __init__.py
    database.py
    repo.py
    services.py
myproject/
  app1/
  app2/
  appN/
manage.py
fabfile.py

在里面deployment/fabric/database.py我有这个代码:

django.settings_module('myproject.settings.devel')

@task
def syncdb():
    local('python manage.py syncdb --noinput')

在我的里面我fabfile.py有我所有的进口:

from deployment.fabric.database import dropdb, createdb, syncdb, createuser
from deployment.fabric.something import blahblah

出于某种原因,我现在似乎无法掌握,在(在部署/织物/数据库.py中发生的)fabfile.py 的设置内部没有保留。DJANGO_SETTINGS_MODULE

起初我错误地意识到os.environ动作不会跨模块持续存在!但这不是真的,因为我立即在我的 django 项目之外构建了一个类似的场景,并使我的错误前提无效。

然后我检查了织物的local功能,发现它本质上是一个包装器subprocess.Popen('...', shell=True)。所以我测试了我之前的实验,subprocess.Popen它仍然保留了跨模块的环境变量。

我不知道这是否与面料的魔术任务导入有关,或者我不掌握一些基本的东西,但以下任何一种方法都可以解决这个问题。

1)使用prefix上下文管理器

def syncdb():
    with prefix('export DJANGO_SETTINGS_MODULE=myproject.settings.devel'):
        local('python manage.py syncdb --noinput')

2)在命令中附加一个--settingslocal(如hynekcer所述)

@task
def syncdb():
    local('python manage.py syncdb --settings=myproject.settings.devel --noinput')

3)在任务中包含settings_module调用(尽管它有点使其目的无效)。

@task
def syncdb():
    django.settings_module('myproject.settings.devel')
    local('python manage.py syncdb --noinput')
于 2012-11-14T18:50:21.587 回答