在BAE中部署Django

之前做了个网站的demo,前日有空,便想弄到bae上试试。其实,部署起来并不复杂,但是限于自己的水平,又是第一次做部署的事情,其中还是遇到很多的麻烦,弄了很久才成功。完成后想想,其实都是些很小细节上出错。今天记录点东西,便于自己日后查阅,也希望能给一些朋友带来些帮助。

首先,我们需要一个bae的账号,由于bae还是内测,要用python需要激活码,这个大家可以发邮件索取或者等着bae放码的时候去抢一个。这些不多说。

拥有账号后,进入bae,创建一个应用,语言选择python,然后创建一个版本,之后会获取一个svn地址。bae是使用svn进行代码的上传和管理的,所以如果不懂svn的话,先学下咯,然后在电脑上安装好svn。这些都不多说啦。bae上有相关的文档。

使用svn将代码checkout到本地。接下来就要开始部署的工作啦。(下面的文字摘自bae文档,可以前往这个地址地址查看。

  1. Django
    BAE预装了Django 1.4版本。如果您需要将基于Django的应用移植到BAE环境中,需要注意如下事项:

  2. CACHE

  3. Cache后端只支持memcache;
  4. 通过bae.core.const.CACHE_ADDR获得Cache地址;

配置示例

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION’: const.CACHE_ADDR,
'TIMEOUT': 60,
  }
}
  1. DATABASE
  2. DATABASE后端目前只支持MySQL;
  3. 从bae.core.const中获取host, port, user, password;
  4. 请通过BAE管理界面,使用PHPMyAdmin来管理维护database, table;

    配置示例

python from bae.core import const DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'cluster11db3', 'USER': const.MYSQL_USER, 'PASSWORD': const.MYSQL_PASS, 'HOST': const.MYSQL_HOST, 'PORT': const.MYSQL_PORT, } }

  1. MAIL
  2. MAIL后端请选用BAE新增的BCMS backend;
  3. 必须配置EMAIL_BCMS_QNAME。可从BAE管理界面上获取bcms_qname;

    配置示例

python EMAIL_BACKEND = 'django.core.mail.backends.bcms.EmailBackend' EMAIL_BCMS_QNAME = '13fe1db4a291e6a57574071e8ff3a52c'

  1. SESSION
  2. SESSION后端支持Cache backend和DB backend;
  3. Cache backend是基于Cache实现的,因此必须配置前述与Cache相关的选项;
  4. DB backend是基于MySQL实现的,因此必须配置前述跟DATABASE相关的选项;

    配置示例

python SESSION_ENGINE = 'django.contrib.sessions.backends.cache' ###或者 SESSION_ENGINE = 'django.contrib.sessions.backends.db'

  1. ADMIN
  2. 在项目目录下创建static目录;
  3. 从Django1.4源码中,将django/contrib/admin/static/admin目录拷贝到刚创建的static目录下;
  4. 修改app.conf,加入对静态文件的支持;

  5. LOGGING

  6. Django使用Python标准库中的logging模块用于日志输出;logging 模块在默认情况下将日志输出到stderr;
  7. 设置WSGIApplication(app, stderr=”log”),将输出到标准出错的日志,重定向到BAE日志服务器。

  8. 开发示例

下面以Django官方网站的示例程序为例,介绍如何在BAE环境中创建Django应用。该示例用到了MySQL服务。

步骤一: 在本机创建Django项目并调试通过。

  • 您需要在自己的开发机上安装Python2.7.2、Django1.4、MySQLdb;
  • 创建工作目录:mkdir django_root && cd django_root;
  • 按照Django开发指南的描述,在本机建立Django Demo项目,并在本地调试通过;
  • 完成turorial 1-4后,目录结构如下:
django_root/
djangodemo/
djangodemo/
polls/
templates/
admin/
polls/
manager.py  

其中templates目录用来保存模板相关的文件。

步骤二: 将项目移植到BAE。

  • 在BAE上创建一个Python项目Django Demo;
  • 创建一个版本,然后通过SVN将项目更新到自己的开发机上;
  • 将第一步创建的Django项目拷贝过来,步骤如下:
cd djangodemo
ls -l ###目录下应该有index.py, app.conf, favicon.ico三个文件;
cp -R XXX/django_root/djangodemo/*
  • 从Django1.4安装目录,或者源码目录,将Admin相关的静态文件拷贝过来:
mkdir -p static
cp -R DJANGO_SOURCE/django/contrib/admin/static/admin static/  
  • 修改settings.py,使用BAE环境提供的MySQL数据库,并通过BAE管理界面提供的PHPMyAdmin来创建 database和table。
  • 修改index.py,修改后的index.py如下所示:
import os  
import sys  
os.environ['DJANGO_SETTINGS_MODULE'] = 'djangodemo.settings'  
path = os.path.dirname(os.path.abspath(__file__)) + '/djangodemo'  
if path not in sys.path:
sys.path.insert(1, path)  
from django.core.handlers.wsgi import WSGIHandler
from bae.core.wsgi import WSGIApplication
application = WSGIApplication(WSGIHandler())
  • 修改app.conf,增加对静态文件的支持。修改后的app.conf如下所示:
handlers:   
- url : /static/(.*)   
script : /static/$1   
- url : /.*   
script : index.py
- expire : .jpg modify 10 years
- expire : .swf modify 10 years
- expire : .png modify 10 years
- expire : .gif modify 10 years
- expire : .JPG modify 10 years
- expire : .ico modify 10 years

完成上述步骤后,就可以访问您的Django应用了。

其实,按照如上的步骤部署一个简单的django应用足够了。实质上,就是几个文件的配置而已,其中一些代码需要根据自己的实际情况进行相应的修改。下面给出一些我的一些相关配置文件。

代码结构如下:

appidxxxx (checkout下来的文件目录)
    |____1 (checkout下来的版本号)
        |____yukiyam (这是你的项目,整体复制到这里吧)
            |____account
            |____blog
            |____static
            |____templates
            |____yukiyam
            |____manage.py
            |____app.conf
            |____index.py

index.py:

#-*- coding:utf-8 -*-
import os
import sys
os.environ['DJANGO_SETTINGS_MODULE'] = 'yukiyam.settings' #settings文件
path = os.path.dirname(os.path.abspath(__file__)) + '/yukiyam'
if path not in sys.path:
sys.path.insert(1,path)
from django.core.handlers.wsgi import WSGIHandler
from bae.core.wsgi import WSGIApplication
application = WSGIApplication(WSGIHandler())
app.conf:
handlers:
- url : /static/(.*)
  script : /static/$1
- url : /.*
  script: index.py  
- expire : .jpg modify 10 years
- expire : .swf modify 10 years
- expire : .png modify 10 years
- expire : .gif modify 10 years
- expire : .JPG modify 10 years
- expire : .ico modify 10 years

settings.py:

# -*- coding:utf-8 -*-
# Django settings for yukiyam project.
import os
import os.path
from bae.core import const #导入bae的const
DEBUG = True
TEMPLATE_DEBUG = DEBUG
base_dir = os.path.dirname(__file__)
HERE = os.path.dirname(os.path.abspath(__file__)) #加这句
HERE = os.path.join(HERE,'../') #加这句
ADMINS = (
# ('Your Name', 'your_email@example.com'),
)
MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE':'django.db.backends.mysql', #bae目前只支持mysql
'NAME': '数据库名', #在bae中使用mysql后你会获取到数据库名
'USER': const.MYSQL_USER, # 使用const获取bae上mysql数据库用户名
'PASSWORD': const.MYSQL_PASS, # 获取密码
'HOST': const.MYSQL_HOST, # 获取host
'PORT': const.MYSQL_PORT, # 获取端口
}
}
CACHES = {
'default':{
'BACKEND':'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION':const.CACHE_ADDR,
'TIMEOUT':60,
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'Asia/Shanghai'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'zh-cn'
LANGUAGE = (
('zh-cn', '简体中文'),
('en-us', 'English'),
)
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True
# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = ''
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
LOGIN_URL = '/login/'
# Make this unique, and don't share it with anybody.
SECRET_KEY = '6r!w4*+w@4zj()tdcr1eyifx4^md=a'
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
ROOT_URLCONF = 'yukiyam.urls'
WSGI_APPLICATION = 'yukiyam.wsgi.application'
TEMPLATE_DIRS = (
os.path.join(HERE, 'templates').replace('\\', '/') #这句代码非常重要,否则无法找到 settings文件
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',  
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'yukiyam',
'blog',
)
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
)
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
}

配置完如上这些之后,使用svn将代码上传到bae上,就可以通过预览查看自己的页面啦。注意,一定要上传正确。由于我受git影响,初次没有使用svn add *,导致没有将所有的代码上传,白白折腾了很久。通过这次部署,我意识到,基本的知识是很重要的,此外,认真的阅读文档也是必要的一步,磨刀不误砍柴工。

好了,以上就是简单的部署过程。good luck。

Go Top
comments powered by Disqus