2012-11-11 51 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