Linux下将Python的Django项目部署到Apache服务器


Posted in Python onDecember 24, 2015

这几天花了点时间,将把django开发好的web项目部署到Apache上,参考了官方的一些文档和互联网上的文档,还是花了比较多的时间,这里把配置的过程说一下。
方便有需要的朋友,可以参考,少走弯路!
1. django项目部署环境说明
操作系统 : Red Hat Enterprise Linux Server release 5.3 (Tikanga) x86_64
apache版本 : httpd-2.2.3-22.el5
mod_wsgi版本 : mod_wsgi-3.2-1.el5 fedora epel可以下载
Django版本 : 1.2.3
python 版本 : 2.5
这里假定Django和Apache已经安装好,并且Django的项目已经开发好。
以上软件包都是通过yum包安装,软件包都是系统标准目录结构!
django开发好的项目目录是 /var/www/html/server,项目目录结构如下(标准django项目目录结构)

#tree -d server/
 server/
 |-- __init__.py
 |-- manage.py
 |-- settings.py
 |-- backend
 |-- static
 |  |-- images
 |  |-- locale
 |  |-- plugins
 |  `-- themes
 |    |-- default
 |    |  `-- images
 |    |-- gray
 |    |  `-- images
 |    `-- icons
 |-- template
 `-- view

2. Apache和mod_wsgi配置
修改wsgi配置(/etc/httpd/conf.d/wsgi.conf)

#cat /etc/httpd/conf.d/wsgi.conf 
 LoadModule wsgi_module modules/mod_wsgi.so
 WSGIScriptAlias / "/var/www/html/server/django.wsgi"
 
 <Directory "/var/www/html/server">
  Order Deny,Allow
  Allow from all
 </Directory>

项目目录中的django.wsgi这个文件是需要新建的,后面会说到如何新建这个文件。
apache使用的标准配置,Apache的DocumentRoot 指向的是 /var/www/html 目录
3. 新建django.wsgi文件
在项目目录/var/www/html/server下新建一个django.wsgi,文件内容如下:

#cat /var/www/html/server/django.wsgi
 # -*- coding: utf-8 -*-
 import os
 import sys
 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
 os.environ['PYTHON_EGG_CACHE'] = '/tmp/.python-eggs'
 current_dir = os.path.dirname(__file__)
 if current_dir not in sys.path: sys.path.append(current_dir) 
 import django.core.handlers.wsgi
 application = django.core.handlers.wsgi.WSGIHandler()

 
第三行 os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' ,这个settings就是指项目目录下的setting.py文件.
第四行 os.environ['PYTHON_EGG_CACHE'] = '/tmp/.python-eggs' ,指定解压egg文件的cache目录,确保运行apache的用户,能够对此目录有读写权限.
第五,六行 将当前目录自动加入到python的搜索路径,如果项目中有自己写的模块,方便使用和发布

最后,这个django.wsgi文件名可以随便取,例如test.wsgi、app.wsgi等等,但是一定要与/etc/httpd/conf.d/wsgi.conf配置文件中配置保持一致。
如果您这里新建的文件名不是django.wsgi而是test.wsgi,那么/etc/httpd/conf.d/wsgi.conf中的配置就应该修改为

WSGIScriptAlias / "/var/www/html/server/test.wsgi"

4. 修改django项目中的setting.py文件
找到项目目录下的setting.py,对于这里就是/var/www/html/server/setting.py。找到其中的TEMPLATE_DIRS,修改为:

TEMPLATE_DIRS = ("/var/www/html/server/template",)

注意: 模板目录在这里一定要用绝对路劲,而不能用相对路径,当然也有方法动态设置模板路劲

PS:关于mod_wsgi
目前mod_wsgi有两种工作模式:

第一种是嵌入模式,类似于mod_python,直接在apache进程中运行,这样的好处是不需要另外增加进程,但是坏处也很明显,所有内存都和apache共享,如果和mod_python一样造成内存漏洞的话,就会危害整个apache。而且如果apache是用worker mpm,mod_wsgi也就强制进入了线程模式,这样子对于非线程安全的程序来说就没法用了。

这种模式下需要在apache的vhost中如下设置:

<span style="font-family: 'times new roman', times;">WSGIScriptAlias /path /path-to-wsgi</span>

即可生效,对于小型脚本的话,直接用这种模式即可。

第二种是后台模式,类似于FastCGI的后台,mod_wsgi会借apache的外壳,另外启动一个或多个进程,然后通过socket通信和apache的进程联系。

这种方式只要使用以下配置即可:

#启动WSGI后台,site1是后台名字


WSGIDaemonProcess site1 processes=1 threads=15 display-name=%{GROUP}

#分配当前上下文应该使用哪个WSGI后台,可以放在Location里面指定
WSGIProcessGroup site1

#根据当前上下文的ProcessGroup分配到对应的后台
WSGIScriptAlias /path /path-to-wsgi

在这种模式下,我们可以通过调节processes和threads的值来设置三种MPM的模式:prefork', 'worker', 'winnt'。

winnt模式

WSGIDaemonProcess example threads=25
wsgi.multithread True
wsgi.multiprocess False

此时processes=1,但是multiprocess为false

如果显式地指出processes为1那么:

WSGIDaemonProcess example processes=1 threads=25
wsgi.multithread True
wsgi.multiprocess True

worker模式

WSGIDaemonProcess example processes=2 threads=25

wsgi.multithread True
wsgi.multiprocess True

preforker模式

WSGIDaemonProcess example processes=5 threads=1
wsgi.multithread False
wsgi.multiprocess True

 

后台模式由于是与apache进程分离了,内存独立,而且可以独立重启,不会影响apache的进程,如果你有多个项目(django),可以选择建立多个后台或者共同使用一个后台。

比如在同一个VirtualHost里面,不同的path对应不同的django项目,可以同时使用一个Daemon:

<span style="font-family: 'times new roman', times;">WSGIDaemonProcess default processes=1 threads=1 display-name=%{GROUP}
 
WSGIProcessGroup default
 
WSGIScriptAlias /project1 “/home/website/project1.wsgi”
 
WSGIScriptAlias /project2 “/home/website/project2.wsgi”</span>

这样子两个django都使用同一个WSGI后台。

也可以把不同的项目分开,分开使用不同的后台,这样开销比较大,但就不会耦合在一起了。

display-name是后台进程的名字,这样方便重启对应的进程,而不需要全部杀掉。

<span style="font-family: 'times new roman', times;">WSGIDaemonProcess site1 processes=1 threads=1 display-name=%{GROUP}
 
WSGIDaemonProcess site2 processes=1 threads=1 display-name=%{GROUP}
 
<Location “/project1″>
WSGIProcessGroup site1
</Location>
WSGIScriptAlias /project1 “/home/website/project1.wsgi”
 
<Location “/project1″>
WSGIProcessGroup site2
</Location>
WSGIScriptAlias /project2 “/home/website/project2.wsgi”</span>

 
对于django 1.0以下的版本,由于官方认定不是线程安全的,所以建议使用多进程单线程模式

processes=n threads=1

对于django 1.0以后,就可以放心的使用多进程多线程模式:

processes=2 threads=64

这样子性能会更好。

Python 相关文章推荐
Python 文件和输入输出小结
Oct 09 Python
python回溯法实现数组全排列输出实例分析
Mar 17 Python
python smtplib模块实现发送邮件带附件sendmail
May 22 Python
在python下读取并展示raw格式的图片实例
Jan 24 Python
用python求一个数组的和与平均值的实现方法
Jun 29 Python
python并发编程多进程之守护进程原理解析
Aug 20 Python
python制作英语翻译小工具代码实例
Sep 09 Python
Win10下安装并使用tensorflow-gpu1.8.0+python3.6全过程分析(显卡MX250+CUDA9.0+cudnn)
Feb 17 Python
django Model层常用验证器及自定义验证器详解
Jul 15 Python
基于python requests selenium爬取excel vba过程解析
Aug 12 Python
python实现简单文件读写函数
Feb 25 Python
Python自动化工具之实现Excel转Markdown表格
Apr 08 Python
在Linux系统上部署Apache+Python+Django+MySQL环境
Dec 24 #Python
在Mac OS上使用mod_wsgi连接Python与Apache服务器
Dec 24 #Python
在Mac OS上搭建Python的开发环境
Dec 24 #Python
详解Python字符串对象的实现
Dec 24 #Python
浅谈Python单向链表的实现
Dec 24 #Python
Python使用面向对象方式创建线程实现12306售票系统
Dec 24 #Python
安装ElasticSearch搜索工具并配置Python驱动的方法
Dec 22 #Python
You might like
利用PHP如何写APP接口详解
2016/08/23 PHP
php 解析xml 的四种方法详细介绍
2016/10/26 PHP
PHP基于openssl实现的非对称加密操作示例
2019/01/11 PHP
JS 分号引起的一段调试问题
2009/06/18 Javascript
jQuery 1.3 和 Validation 验证插件1.5.1
2009/07/09 Javascript
jquery 学习之二 属性(html()与html(val))
2010/11/25 Javascript
window.dialogArguments 使用说明
2011/04/11 Javascript
js遍历、动态的添加数据的小例子
2013/06/22 Javascript
如何在JavaScript中实现私有属性的写类方式(一)
2013/12/04 Javascript
node.js中的fs.utimes方法使用说明
2014/12/15 Javascript
jQuery实现获取table表格第一列值的方法
2016/03/01 Javascript
JS触摸屏网页版仿app弹窗型滚动列表选择器/日期选择器
2016/10/30 Javascript
js+html制作简单日历的方法
2017/06/27 Javascript
jQuery plugin animsition使用小结
2017/09/14 jQuery
微信小程序仿美团城市选择
2018/06/06 Javascript
AngularJS与后端php的数据交互方法
2018/08/13 Javascript
微信小程序调用摄像头隐藏式拍照功能
2018/08/22 Javascript
[49:30]DOTA2-DPC中国联赛正赛 Dragon vs Dynasty BO3 第二场 3月4日
2021/03/11 DOTA
python按照多个字符对字符串进行分割的方法
2015/03/17 Python
Python 安装setuptools和pip工具操作方法(必看)
2017/05/22 Python
Centos7 Python3下安装scrapy的详细步骤
2018/03/15 Python
使用python读取csv文件快速插入数据库的实例
2018/06/21 Python
python中文编码与json中文输出问题详解
2018/08/24 Python
python每天定时运行某程序代码
2019/08/16 Python
Matplotlib使用Cursor实现UI定位的示例代码
2020/03/12 Python
Django-celery-beat动态添加周期性任务实现过程解析
2020/11/26 Python
美国摄影爱好者购物网站:Focus Camera
2016/10/21 全球购物
美国在线咖啡、茶和餐厅供应商:LollicupStore
2018/05/04 全球购物
爱普生美国官网:Epson美国
2018/11/05 全球购物
2014年检验员工作总结
2014/11/19 职场文书
初中学生操行评语
2014/12/26 职场文书
我是特种兵观后感
2015/06/11 职场文书
教师理论学习心得体会
2016/01/21 职场文书
Mysql关于数据库是否应该使用外键约束详解说明
2021/10/24 MySQL
Java 在生活中的 10 大应用
2021/11/02 Java/Android
docker-compose部署Yapi的方法
2022/04/08 Servers