问题:如何配置Django以进行简单的开发和部署?
I tend to use SQLite when doing Django
development, but on a live server something more robust is
often needed (MySQL/PostgreSQL, for example).
Invariably, there are other changes to make to the Django
settings as well: different logging locations / intensities,
media paths, etc.
How do you manage all these changes to make deployment a
simple, automated process?
回答 0
更新: django-configurations已发布,对于大多数人来说,它可能比手动执行更好。
如果您希望手动进行操作,则我先前的答案仍然适用:
我有多个设置文件。
settings_local.py
-特定于主机的配置,例如数据库名称,文件路径等。
settings_development.py
-用于开发的配置,例如DEBUG = True
。
settings_production.py
-用于生产的配置,例如SERVER_EMAIL
。
我将所有这些与一个settings.py
首先导入的文件捆绑在一起settings_local.py
,然后再将另外两个文件之一捆绑在一起。它决定它通过两个设置加载内settings_local.py
– DEVELOPMENT_HOSTS
和PRODUCTION_HOSTS
。 settings.py
来电platform.node()
以查找正在其上运行的计算机的主机名,然后在列表中查找该主机名,并根据在其中找到该主机名的列表加载第二个设置文件。
这样,您真正需要担心的唯一事情就是使settings_local.py
文件与主机特定的配置保持最新,并且其他所有内容都会自动处理。
在此处查看示例。
Update: django-configurations has been released which is probably a better option for most people than doing it manually.
If you would prefer to do things manually, my earlier answer still applies:
I have multiple settings files.
settings_local.py
– host-specific configuration, such as database name, file paths, etc.
settings_development.py
– configuration used for development, e.g. DEBUG = True
.
settings_production.py
– configuration used for production, e.g. SERVER_EMAIL
.
I tie these all together with a settings.py
file that firstly imports settings_local.py
, and then one of the other two. It decides which to load by two settings inside settings_local.py
– DEVELOPMENT_HOSTS
and PRODUCTION_HOSTS
. settings.py
calls platform.node()
to find the hostname of the machine it is running on, and then looks for that hostname in the lists, and loads the second settings file depending on which list it finds the hostname in.
That way, the only thing you really need to worry about is keeping the settings_local.py
file up to date with the host-specific configuration, and everything else is handled automatically.
Check out an example here.
回答 1
就个人而言,我为该项目使用一个settings.py,我只是让它查找所在的主机名(我的开发机器的主机名以“ gabriel”开头,所以我只有这样:
import socket
if socket.gethostname().startswith('gabriel'):
LIVEHOST = False
else:
LIVEHOST = True
然后在其他地方,我有类似的东西:
if LIVEHOST:
DEBUG = False
PREPEND_WWW = True
MEDIA_URL = 'http://static1.grsites.com/'
else:
DEBUG = True
PREPEND_WWW = False
MEDIA_URL = 'http://localhost:8000/static/'
等等。可读性稍差,但是它可以正常工作,并且省去了处理多个设置文件的麻烦。
Personally, I use a single settings.py for the project, I just have it look up the hostname it’s on (my development machines have hostnames that start with “gabriel” so I just have this:
import socket
if socket.gethostname().startswith('gabriel'):
LIVEHOST = False
else:
LIVEHOST = True
then in other parts I have things like:
if LIVEHOST:
DEBUG = False
PREPEND_WWW = True
MEDIA_URL = 'http://static1.grsites.com/'
else:
DEBUG = True
PREPEND_WWW = False
MEDIA_URL = 'http://localhost:8000/static/'
and so on. A little bit less readable, but it works fine and saves having to juggle multiple settings files.
回答 2
在settings.py的结尾,我有以下内容:
try:
from settings_local import *
except ImportError:
pass
这样,如果我想覆盖默认设置,则只需将settings_local.py放在settings.py旁边。
At the end of settings.py I have the following:
try:
from settings_local import *
except ImportError:
pass
This way if I want to override default settings I need to just put settings_local.py right next to settings.py.
回答 3
我有两个文件。settings_base.py
其中包含通用/默认设置,并且已签入源代码管理。每个部署都有一个单独的settings.py
,从头from settings_base import *
开始执行,然后根据需要进行覆盖。
I have two files. settings_base.py
which contains common/default settings, and which is checked into source control. Each deployment has a separate settings.py
, which executes from settings_base import *
at the beginning and then overrides as needed.
回答 4
我发现的最简单的方法是:
1)使用默认的settings.py进行本地开发,以及2)创建一个production-settings.py,开头为:
import os
from settings import *
然后只需覆盖生产中不同的设置:
DEBUG = False
TEMPLATE_DEBUG = DEBUG
DATABASES = {
'default': {
....
}
}
The most simplistic way I found was:
1) use the default settings.py for local development and 2)
create a production-settings.py starting with:
import os
from settings import *
And then just override the settings that differ in production:
DEBUG = False
TEMPLATE_DEBUG = DEBUG
DATABASES = {
'default': {
....
}
}
回答 5
在某种程度上相关,关于使用多个数据库部署Django本身的问题,您可能需要看一下Djangostack。您可以下载一个完全免费的安装程序,该程序允许您安装Apache,Python,Django等。在安装过程中,我们允许您选择要使用的数据库(MySQL,SQLite,PostgreSQL)。在内部自动进行部署时,我们会广泛使用安装程序(它们可以在无人值守模式下运行)。
Somewhat related, for the issue of deploying Django itself with multiple databases, you may want to take a look at Djangostack. You can download a completely free installer that allows you to install Apache, Python, Django, etc. As part of the installation process we allow you to select which database you want to use (MySQL, SQLite, PostgreSQL). We use the installers extensively when automating deployments internally (they can be run in unattended mode).
回答 6
我的settings.py文件位于外部目录中。这样,就不会将其检入源代码管理或被部署覆盖。我将其与所有默认设置一起放入Django项目下的settings.py文件中:
import sys
import os.path
def _load_settings(path):
print "Loading configuration from %s" % (path)
if os.path.exists(path):
settings = {}
# execfile can't modify globals directly, so we will load them manually
execfile(path, globals(), settings)
for setting in settings:
globals()[setting] = settings[setting]
_load_settings("/usr/local/conf/local_settings.py")
注意:如果您不信任local_settings.py,这将非常危险。
I have my settings.py file in an external directory. That way, it doesn’t get checked into source control, or over-written by a deploy. I put this in the settings.py file under my Django project, along with any default settings:
import sys
import os.path
def _load_settings(path):
print "Loading configuration from %s" % (path)
if os.path.exists(path):
settings = {}
# execfile can't modify globals directly, so we will load them manually
execfile(path, globals(), settings)
for setting in settings:
globals()[setting] = settings[setting]
_load_settings("/usr/local/conf/local_settings.py")
Note: This is very dangerous if you can’t trust local_settings.py.
回答 7
除了吉姆提到的多个设置文件,我也倾向于地方两个设置成我的顶部settings.py文件BASE_DIR
和BASE_URL
设置的代码和URL到现场的基地的路径,所有其他的设置被修改将自己附加到这些。
BASE_DIR = "/home/sean/myapp/"
例如 MEDIA_ROOT = "%smedia/" % BASEDIR
因此,在移动项目时,我只需要编辑这些设置,而无需搜索整个文件。
我还建议您查看一下能够促进远程部署自动化的fabric和Capistrano(Ruby工具,但是它可以用于部署Django应用程序)。
In addition to the multiple settings files mentioned by Jim, I also tend to place two settings into my settings.py file at the top BASE_DIR
and BASE_URL
set to the path of the code and the URL to the base of the site, all other settings are modified to append themselves to these.
BASE_DIR = "/home/sean/myapp/"
e.g. MEDIA_ROOT = "%smedia/" % BASEDIR
So when moving the project I only have to edit these settings and not search the whole file.
I would also recommend looking at fabric and Capistrano (Ruby tool, but it can be used to deploy Django applications) which facilitate automation of remote deployment.
回答 8
好吧,我使用以下配置:
在settings.py的末尾:
#settings.py
try:
from locale_settings import *
except ImportError:
pass
在locale_settings.py中:
#locale_settings.py
class Settings(object):
def __init__(self):
import settings
self.settings = settings
def __getattr__(self, name):
return getattr(self.settings, name)
settings = Settings()
INSTALLED_APPS = settings.INSTALLED_APPS + (
'gunicorn',)
# Delete duplicate settings maybe not needed, but I prefer to do it.
del settings
del Settings
Well, I use this configuration:
At the end of settings.py:
#settings.py
try:
from locale_settings import *
except ImportError:
pass
And in locale_settings.py:
#locale_settings.py
class Settings(object):
def __init__(self):
import settings
self.settings = settings
def __getattr__(self, name):
return getattr(self.settings, name)
settings = Settings()
INSTALLED_APPS = settings.INSTALLED_APPS + (
'gunicorn',)
# Delete duplicate settings maybe not needed, but I prefer to do it.
del settings
del Settings
回答 9
这么多复杂的答案!
每个settings.py文件都附带:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
我使用该目录来设置DEBUG变量,如下所示(用您的开发代码所在的directoy代替):
DEBUG=False
if(BASE_DIR=="/path/to/my/dev/dir"):
DEBUG = True
然后,每次移动settings.py文件时,DEBUG将为False,这是您的生产环境。
每当您需要与开发环境中不同的设置时,只需使用:
if(DEBUG):
#Debug setting
else:
#Release setting
So many complicated answers!
Every settings.py file comes with :
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
I use that directory to set the DEBUG variable like this (reaplace with the directoy where your dev code is):
DEBUG=False
if(BASE_DIR=="/path/to/my/dev/dir"):
DEBUG = True
Then, every time the settings.py file is moved, DEBUG will be False and it’s your production environment.
Every time you need different settings than the ones in your dev environment just use:
if(DEBUG):
#Debug setting
else:
#Release setting
回答 10
我认为这取决于站点的大小,是否需要逐步使用SQLite,我已经在几个较小的实时站点上成功使用了SQLite,并且运行良好。
I think it depends on the size of the site as to whether you need to step up from using SQLite, I’ve successfully used SQLite on several smaller live sites and it runs great.
回答 11
我使用环境:
if os.environ.get('WEB_MODE', None) == 'production' :
from settings_production import *
else :
from settings_dev import *
我相信这是一种更好的方法,因为最终您需要针对测试环境进行特殊设置,并且可以轻松地将其添加到此条件中。
I use environment:
if os.environ.get('WEB_MODE', None) == 'production' :
from settings_production import *
else :
from settings_dev import *
I believe this is a much better approach, because eventually you need special settings for your test environment, and you can easily add it to this condition.
回答 12
这是一个较旧的文章,但是我认为如果我添加这个有用的内容library
,它将简化事情。
使用Django配置
快速开始
pip install django-configurations
然后子类化包含的配置。配置类在项目的settings.py或用于存储设置常量的任何其他模块中,例如:
# mysite/settings.py
from configurations import Configuration
class Dev(Configuration):
DEBUG = True
将DJANGO_CONFIGURATION
环境变量设置为您刚刚创建的类的名称,例如~/.bashrc
:
export DJANGO_CONFIGURATION=Dev
并将DJANGO_SETTINGS_MODULE
环境变量照常导入模块导入路径,例如在bash中:
export DJANGO_SETTINGS_MODULE=mysite.settings
另外,--configuration
在使用Django管理命令时,请按照Django默认--settings
命令行选项的方式提供选项,例如:
python manage.py runserver --settings=mysite.settings --configuration=Dev
为了使Django使用您的配置,您现在必须修改您的manage.py或wsgi.py脚本,以使用django-configurations的相应启动程序版本,例如,使用django-configurations 的典型manage.py如下所示:
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.management import execute_from_command_line
execute_from_command_line(sys.argv)
请注意,在第10行中,我们不使用通用工具django.core.management.execute_from_command_line
,而是使用configurations.management.execute_from_command_line
。
这同样适用于您的wsgi.py文件,例如:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.wsgi import get_wsgi_application
application = get_wsgi_application()
这里我们不使用默认django.core.wsgi.get_wsgi_application
功能,而是使用configurations.wsgi.get_wsgi_application
。
而已!现在,您可以将项目与manage.py以及您最喜欢的启用WSGI的服务器一起使用。
This is an older post but I think if I add this useful library
it will simplify things.
Use django-configuration
Quickstart
pip install django-configurations
Then subclass the included configurations.Configuration class in your project’s settings.py or any other module you’re using to store the settings constants, e.g.:
# mysite/settings.py
from configurations import Configuration
class Dev(Configuration):
DEBUG = True
Set the DJANGO_CONFIGURATION
environment variable to the name of the class you just created, e.g. in ~/.bashrc
:
export DJANGO_CONFIGURATION=Dev
and the DJANGO_SETTINGS_MODULE
environment variable to the module import path as usual, e.g. in bash:
export DJANGO_SETTINGS_MODULE=mysite.settings
Alternatively supply the --configuration
option when using Django management commands along the lines of Django’s default --settings
command line option, e.g.:
python manage.py runserver --settings=mysite.settings --configuration=Dev
To enable Django to use your configuration you now have to modify your manage.py or wsgi.py script to use django-configurations’ versions of the appropriate starter functions, e.g. a typical manage.py using django-configurations would look like this:
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.management import execute_from_command_line
execute_from_command_line(sys.argv)
Notice in line 10 we don’t use the common tool django.core.management.execute_from_command_line
but instead configurations.management.execute_from_command_line
.
The same applies to your wsgi.py file, e.g.:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
os.environ.setdefault('DJANGO_CONFIGURATION', 'Dev')
from configurations.wsgi import get_wsgi_application
application = get_wsgi_application()
Here we don’t use the default django.core.wsgi.get_wsgi_application
function but instead configurations.wsgi.get_wsgi_application
.
That’s it! You can now use your project with manage.py and your favorite WSGI enabled server.
回答 13
实际上,您可能应该考虑为您的开发和生产环境使用相同(或几乎相同)的配置。否则,会不时出现“嘿,它可以在我的机器上工作”之类的情况。
因此,为了自动化部署并消除那些WOMM问题,只需使用Docker即可。
In fact you should probably consider having the same (or almost the same) configs for your development and production environment. Otherwise, situations like “Hey, it works on my machine” will happen from time to time.
So in order to automate your deployment and eliminate those WOMM issues, just use Docker.