2012-11-11 34 views
3

我有我的项目的设置如下方案:Python的织物“本地”功能不尊重环境变量DJANGO_SETTINGS_MODULE

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. 

一些其他注意事项:

  • project函数在这里不适用,因为它假设(内部)所有的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不起作用像广告。

+1

我无法重现该问题。环境变量DJANGO_SETTINGS_MODULE和settings_module适用于我。你使用Django 1.4吗?你可以在不同的机器上重现它吗? – hynekcer

+0

@hynekcer当你说你不能重现问题时,我认为你有一个类似'settings'的方案,而不是一个简单的'settings.py'?是的,我有django 1.4和最新的pip可安装结构。 – rantanplan

+0

是的,配置'myproject/settings/anyfile.py',一个空的'myproject/settings/__ init __。py'和和你一样的fabfile.py。 – hynekcer

回答

1

那么我发现问题,但我不知道该怎么做。

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

尽管我的django项目的结构与我所描述的完全相同,但我的结构 结构稍微复杂一些。

在本质上我遵循this part of fabric's documentation

一些模式下完整的结构进行了说明:

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 

出于某种原因,我目前无法掌握,在fabfile.py 之内,DJANGO_SETTINGS_MODULE(发生在deployment/fabric/database.py中)的设置不会保留。

起初我来到虚假的认识,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)local命令附加一个--settings值(如由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') 
1

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

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

谢谢你的回答。我知道我可以这样做,我会更新我的问题来反映这一点。但基本上我想知道'local'函数究竟发生了什么,以及为什么'settings_module'函数不能像广告一样工作。要么我做错了什么,或者有错误。 – rantanplan

+0

阅读我的答案了解更多详情。我赞成你的回答,因为这是解决这个问题的方法之一。 – rantanplan