编辑: 请记住此答案受平台限制,并且由于OpenShift服务Django的平台可能会更改,因此此答案可能会失效。截至2016年4月1日,此答案在其全部范围内仍然有效。
很多时候我也遇到过这种情况,由于我必须挂载至少5个应用程序,所以我不得不创建自己的生命周期:
- 不要使用Django插件,而是使用Python 2.7插件。使用Django插件并尝试更新Django版本会带来许多麻烦,除非您从头开始建立。
通过git克隆您的存储库。您将获得yourproject
和...
# git clone yourrepo@rhcloud.com:app.git yourproject <- replace it with your actual openshift repo address
yourproject/
+---wsgi.py
+---setup.py
*---.openshift/ (with its contents - I omit them now)
为您在本地机器上克隆的全新存储库创建一个虚拟环境。激活它并通过 pip
安装 Django 和所有需要的依赖项(例如新的 Pillow 包,MySQL 数据库包等)。在其中创建一个 django 项目,比如说yourdjproject。同时,创建一个 wsgi/static
目录,并在其中放置一个空的、虚拟的文件(例如.gitkeep
- 这只是约定俗成的名称:你可以使用任何你想要的名称)。
mkvirtualenv myenvironment
workon myenvironment
pip install Django[==x.y[.z]]
cd path/to/yourproject/
django-admin.py startproject yourjdproject .
mkdir -p wsgi/static
touch wsgi/static/.gitkeep
在那里创建一个Django应用程序。比如,你的应用程序为yourapp。将其包含到你的项目中。
你会得到类似于以下内容(对于Django 1.7):
yourproject/
+---wsgi/
| +---static/
| +---.gitkeep
+---wsgi.py
+---setup.py
+---.openshift/ (with its contents - I omit them now)
+---yourdjproject/
| +----__init__.py
| +----urls.py
| +----settings.py
| +----wsgi.py
+---+yourapp/
+----__init__.py
+----models.py
+----views.py
+----tests.py
+----migrations
+---__init__.py
按照惯例设置你的Django应用程序(此处不详细描述)。请记得在setup.py文件中相应地包含你安装的所有依赖项(此处不介绍原因,但是setup.py是包安装程序,openshift在每个部署时使用它来重新安装你的应用程序,所以要随时更新依赖项)。
为你的模型创建迁移。编辑openshift提供的WSGI脚本如下。你将在包含虚拟环境之后包含django WSGI应用程序(openshift为Python Cartridges创建了一个虚拟环境),因此pythonpath将被正确设置。
import os
virtenv = os.environ['OPENSHIFT_PYTHON_DIR'] + '/virtenv/'
virtualenv = os.path.join(virtenv, 'bin/activate_this.py')
try:
execfile(virtualenv, dict(__file__=virtualenv))
except IOError:
pass
from yourdjproject.wsgi import application
编辑.openshift/action_hooks中的钩子以自动执行数据库同步和媒体管理:
构建钩子
#!/bin/bash
if [ ! -d ${OPENSHIFT_DATA_DIR}media ]; then
mkdir -p ${OPENSHIFT_DATA_DIR}media
fi
ln -snf ${OPENSHIFT_DATA_DIR}media $OPENSHIFT_REPO_DIR/wsgi/static/media
部署钩子。
#!/bin/bash
source $OPENSHIFT_HOMEDIR/python/virtenv/bin/activate
cd $OPENSHIFT_REPO_DIR
echo "Executing 'python manage.py migrate'"
python manage.py migrate
echo "Executing 'python manage.py collectstatic --noinput'"
python manage.py collectstatic --noinput
现在你已经准备好了WSGI,通过导入指向Django WSGI,并且你的脚本正在运行。现在是考虑静态文件和媒体文件存放位置的时候了。编辑Django设置,告诉程序你想要这些文件存放的位置:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static')
MEDIA_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static', 'media')
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'yourjdproject', 'static'),)
TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'yourjdproject', 'templates'),)
创建一个示例视图、示例模型、示例迁移,并将所有内容PUSH。
编辑请记得设置正确的环境参数,以便您可以在本地环境和openshift中进行测试和运行(通常这涉及到有一个local_settings.py
文件,在必要时导入该文件,但我将省略该部分,并将所有内容放在同一个文件中)。请仔细阅读此文件,因为像yourlocaldbname这样的值您必须根据实际情况进行设置:
"""
Django settings for yourdjproject project.
For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
ON_OPENSHIFT = False
if 'OPENSHIFT_REPO_DIR' in os.environ:
ON_OPENSHIFT = True
SECRET_KEY = '60e32dn-za#y=x!551tditnset(o9b@2bkh1)b$hn&0$ec5-j7'
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'yourapp',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
ROOT_URLCONF = 'yourdjproject.urls'
WSGI_APPLICATION = 'yourdjproject.wsgi.application'
if ON_OPENSHIFT:
DEBUG = True
TEMPLATE_DEBUG = False
ALLOWED_HOSTS = ['*']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'youropenshiftgenerateddatabasename',
'USER': os.getenv('OPENSHIFT_MYSQL_DB_USERNAME'),
'PASSWORD': os.getenv('OPENSHIFT_MYSQL_DB_PASSWORD'),
'HOST': os.getenv('OPENSHIFT_MYSQL_DB_HOST'),
'PORT': os.getenv('OPENSHIFT_MYSQL_DB_PORT'),
}
}
else:
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'yourlocaldbname',
'USER': 'yourlocalusername',
'PASSWORD': 'yourlocaluserpassword',
'HOST': 'yourlocaldbhost',
'PORT': '3306',
}
}
LANGUAGE_CODE = 'yr-LC'
TIME_ZONE = 'Your/Timezone/Here'
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static')
MEDIA_ROOT = os.path.join(BASE_DIR, 'wsgi', 'static', 'media')
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'yourdjproject', 'static'),)
TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'yourdjproject', 'templates'),)
Git add、commit、push,尽情享受。
cd path/to/yourproject/
git add .
git commit -m "Your Message"
git push origin master # THIS COMMAND WILL TAKE LONG
# git enjoy
您的Django示例应用程序即将准备就绪!但是,如果您的应用程序具有外部依赖项,它将会毫无明显原因地崩溃。这就是我告诉您开发一个简单应用程序的原因。
现在是让您的依赖项正常工作的时候了。
[
未经测试!] 您可以编辑部署挂钩,并在命令
cd $OPENSHIFT_REPO_DIR
后添加一个命令,例如:
pip install -r requirements.txt
,假设该文件在您的项目中存在。
pip
应该存在于您的虚拟环境中,但如果不存在,则可以查看下一个解决方案。
另外,setup.py 在 OpenShift 中是一种已提供的方法。我多次尝试过——假设 requirements.txt 文件存在——如下所示:
1. 打开文件并读取所有行。
2. 对于每一行,如果它有 #,则删除 # 及其后面的内容。
3. 剥离前导和尾随空格。
4. 丢弃空行,并将结果(即剩余行)作为数组分配给 setup.py 文件中的
install_requires=
关键字参数。
5. 该结果必须分配给 setup.py 文件中的 setup 调用中的
install_requires=
关键字参数。
很抱歉我没有在教程中包括这些内容! 但是您需要在服务器上安装 Django。也许这是一个显而易见的建议,每个 Python 开发人员都应该事先知道。但是,借此机会我强调:将适当的 Django 依赖项包含在 requirements.txt 中(或者根据您是否使用 requirements.txt 文件而包含在 setup.py 中),就像包含任何其他依赖项一样。
这应该有助于您挂载 Django 应用程序,并且花费了我很多时间来标准化该过程。享受它,并且如果出现问题,请毫不犹豫地通过评论联系我。
编辑(对于那些不希望在本文的评论中找到答案的同类人员):请记住,如果您在 Windows 下编辑构建或部署挂钩文件并推送文件,则它们将以 0644 权限飞到服务器上,因为 Windows 不支持 Unix 的此权限方案,并且无法分配权限,因为这些文件没有任何扩展名。
您会注意到这一点,因为在部署时不会执行您的脚本。因此,请尽量仅从基于 Unix 的系统部署这些文件。
编辑 2:您可以使用 Git 钩子(例如 pre_commit)为某些文件设置权限,例如流水线脚本(构建、部署等)。有关详细信息,请参见 @StijndeWitt 和 @OliverBurdekin 在此答案中的评论,以及
此问题。