您的位置:首页 > 运维架构 > Nginx

CentOS + Python3.6+ Django2.0 + uwsgi + nginx + mysql web发布环境搭建

2017-11-02 17:27 991 查看
目录:

CentOS上升级Python
安装easy_install和pip
uwsgi安装及测试
Django安装及测试
连接uwsgi与Django
nginx安装及测试
连接uwsgi与nginx
连接uwsgi与Django与nginx
uwsgi ini
mysql安装设置
python3 Django mysql连接及测试
快速搭建blog测试
Pycharm开发
如果只是想学习django开发直接用django本身自带的开发用服务器即可。
1. CentOS上升级Python

用的系统是CentOS 6.4,其上python版本是2.6,而Django支持的版本是2.7+,又考虑到网页语言用UTF-8,而python3+默认字符已变为Unicode,所以选择python3版本,小菜理解,不知对错。
前后安装python一共4遍,每次到后面就会遇到因为编译时缺少某某模块的问题,不得不又安装了模块重新编译,这几个模块是,
yum install zlib zlib-devel
yum install bzip2 bzip2-devel
yum install openssl openssl-devel
yum install sqlite-devel
安装完之后再tar it,这里要说的是,因为有自带的pyhton了,所以我们安装到新的目录,不要覆盖。
./configure --prefix=/usr/local/python3.6 && make && make install
在/usr/bin下我们可以看到有python,python2,python2.6,其实都是一个文件,我们把自己的ln过去,
ln -s /usr/local/python3.6/bin/python3.6 /usr/bin/python
python -V
可以看到版本改变了。但是这时用了yum发现报错了,唉,
vim /usr/bin/yum
#! /usr/bin/python 改为 #! /usr/bin/python2.6
如此即可,CentOS下python安装告一段落。
(注:如果接下来不想频繁做ln -s链接,就把/usr/local/python3.3/bin设置为环境变量吧,自行网补。)
2. 安装easy_install和pip

可能对各位很简单,但是对我来说太难了,
wget https://bootstrap.pypa.io/ez_setup.py python ez_setup.py
ln -s /usr/local/python3.6/bin/easy_install /usr/bin/easy_install
wget python' target='_blank'>https://raw.github.com/pypa/pip/master/contrib/get-pip.py
python get-pip.py
像教程上说的那样,这样安装完成后应该可以直接执行pip -V了,结果我就是找不到命令,还是pip本来就不给自动设置成为命令,去python目录下看看也找不到pip文件,该ln哪个文件,于是半天未果后,就采取了这样的办法,
(注:想要yum安装pip还要先安装EPEL,详见http://xmodulo.com/how-to-set-up-epel-repository-on-centos.html,选择相应版本,相应解决方案。有时侯windows下配置简单,有时候又必须选择linux。)
yum install python-pip
pip -V
然后报错了,人总是让现实搞的追求越来越低,能报错太高兴了,说明已经有这个命令了。查看错误是版本冲突,因为我们上面安装过1.5.6(目前最新),yum安装的1.3几吧,于是我查看下pip文件,出于本能
把1.3.几全改成了1.5.6,
vim /usr/bin/pip
修改后:
#!/usr/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'pip==1.5.6','console_scripts','pip'
__requires__ = 'pip==1.5.6'
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.exit(
load_entry_point('pip==1.5.6', 'console_scripts', 'pip')()
)
机智的我备份了下,然后yum remove python-pip,果然pip没了,我把备份还原过来,pip终于正常使用了。真难!

3. uwsgi安装及测试

搞了许久后终于来到正题,为什么选择uwsgi呢,是因为apache的mod_wsgi配置太难了,网上找到的资料,各人有各人的步骤,各人有各人的路径,这我学这个不像,学那个不像,只学一个人的行吗,遇到问题还是要去的别人的,毕竟每个人遇到的问题不同。在这长达一天的start:邂逅问题,查找问题,解决问题,goto start中发现了uwsgi,号称专治mod_wsgi各种顽疾,又是搭配nginx,于是就来搭建这个吧。
pip install uwgsi
ln -s /usr/local/python3.6/bin/uwsgi /usr/bin/uwsgi
现在来测试一下,
vim test.py
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"] # python3
#return ["Hello World"] # python2
uwsgi --http :8001 --wsgi-file test.py
此时访问http://localhost:8001可见Hello World,成功。
(补:成功不易啊。为什么到处的教程都是写的return “xxxxx”,结果网页无输出,我跋山涉水找到官网才发现要加b,原因当然是版本不同,其中的[]加不加无所谓,但是在python3中,因为字符默认是unicode了,所以必须进行编码。其中的b”xxx”也可以换为”xxx”.encode(‘utf-8′),但是在文前加上#-*- coding: UTF-8 -*-却不行呢。
在python3中文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。
uwsgi -s :8001 –wsgi-file test.py,访问时会出现invalid request block size: 21573 (max 4096)…skip,因为usgi参数-s表示以socket方式提供通信端口,默认的协议是tcp。当通过nginx访问uwsgi,就无所谓了。)
4. Django安装及测试

此处测试用到sqlite模块。
pip install django
cd /usr/local/python3.6/bin/
python django-admin.py startproject myproject
cd myproject
python manage.py runserver 0.0.0.0:8002
打开浏览器访问http://localhost:8002显示It worked!..,成功。现在学聪明了,多看几个教程,联系着来,不容易出错。
5. 连接uwsgi与Django

不要看到一些教程上有就也跟着建立个django_wsgi,现在版本不需要了,直接myproject.wsgi即可。
uwsgi --http :8004 --chdir /home/wwwroot/default/myproject --module myproject.wsgi
成功可见It worked!。
6. nginx安装及测试
yum install nginx
service nginx start
浏览器访问localhost,可见Welcome to nginx on EPEL!,成功。但是不要用这种方式,它自动安装的相关配置我们不清楚,所以一定要选择源码安装。因为我之前的贪简单,后面遇到很多permission问题,最后又重装了下,但是下面的很多章节都是在上面的配置方式下进行的,懒得修改了。
在这之前,有相当多的环境要安装,尤其是Pcre。
yum install patch make cmake gcc gcc-c++ gcc-g77 flex bison file libtool libtool-libs autoconf kernel-devel libjpeg libjpeg-devel libpng libpng-devel libpng10 libpng10-devel gd gd-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glib2 glib2-devel bzip2 bzip2-devel libevent libevent-devel ncurses ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl openssl-devel vim-minimal nano fonts-chinese gettext gettext-devel ncurses-devel gmp-devel pspell-devel unzip libcap diffutils
wget http://soft.vpser.net/web/pcre/pcre-8.30.tar.gz tar it configure make make install
groupadd www
useradd -s /sbin/nologin -g www www
wget http://soft.vpser.net/web/nginx/nginx-1.6.2.tar.gz tar it
./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-ipv6
make && make install
安装完成后,启动方法有2个:
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
/usr/local/nginx/sbin/nginx
我懂得不深,所以用第一个,因为每次都会重读配置文件。这时又提示找不到libpcre.so.1,于是我们可以
find / -name "libpcre.so.*"
你会发现/lib64下有libpcre.so.0.0.1,32位就是/lib下面,我们做一下ln,
ln -s /lib64/libpcre.so.0.0.1 /lib64/libpcre.so.1
这时再次启动nginx,没有错误,打开浏览器访问http://localhost,可见Welcome to nginx on EPEL!,成功。
7. 连接uwsgi与nginx

nginx用户权限很愁人啊,但是网上很少有人遇到我的问题,一开始想变更日志路径,nginx.conf中可见user是nginx,我甚至把一个文件夹权限改成a+rwx,属主改为nginx仍然permission denied。而且每次启动总找不到/var/run/nginx.pid,所以service nginx start各种不能用。最后无奈启动方法变为/usr/sbin/nginx -c /etc/nginx/nginx.conf即可。
一开始选择在conf.d目录下写myproject.conf的做法,但是为了避免到处permission denied,本着最小改动的原则,仅修改nginx.conf如下:
vim /etc/nginx/nginx.conf
在http{}中添加如下:
upstream django {
server 127.0.0.1:8001; # for a web port socket
}
server {
listen      8000;
server_name xqlm.com; # substitute your machine's IP address or FQDN
charset     utf-8;
client_max_body_size 75M;   # adjust to taste
#location /media  {
#    alias /path/to/your/mysite/media;  # your Django project's media files - amend as required
#}
#location /static {
#    alias /path/to/your/mysite/static; # your Django project's static files - amend as required
#}
# Finally, send all non-media requests to the Django server.
location / {
root        /你的工程目录/myproject;
uwsgi_pass  django;
include     uwsgi_params; # the uwsgi_params file you installed
}
}
upstream django {
server 127.0.0.1:8001; # for a web port socket
}

location / {
root /你的工程目录/myproject;
uwsgi_pass django;
include uwsgi_params; # the uwsgi_params file you installed
}
(重要)

修改完成后,
uwsgi --socket :8001 --wsgi-file test.py
浏览器访问http://localhost:8000,出现Hello world!,表示成功。这里有必要说明这几个端口的关系,用户的访问是8000,对应着nginx.conf中的sever listen,然后nginx会把这些信息转达给nginx.conf中的django 8001,也就是uwsgi命令启动时监听的端口。那么直接转发给uwsgi不就可以吗,为什么中间还要插个nginx?我只好用网上的回答搪塞下“单单只有uWSGI是不够的,在实际的部署环境中,Nginx是必不可少的工具。nginx具备优秀的静态内容处理能力,然后将动态内容转发给uWSGI服务器,这样可以达到很好的客户端响应。”。上面的server中你会发现注释掉的location /static和/media,分别是表示静态内容和动态内容,但是现在我们是个空项目,用不到,后面用到再说。
8. 连接uwsgi与Django与nginx
uwsgi --socket :8001 --module myproject.wsgi
(如果出现permisson问题酌情添加 --chmod-socket=664 或 666,一般是因为用mysite.sock才会引起,指定端口不会。)
前面每步都测试,每步都正确,到现在应该没有问题了,直接浏览器访问http://localhost:8000,现在是It worked!了。
9. uwsgi ini

有没有觉得每次uwsgi跟一长串路径不方便,那就写成一个ini文件吧,xml也可以,这里只给出ini版本的,
vim myproject_uwsgi.ini
# mysite_uwsgi.ini file
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir           = /home/wwwroot/default/myproject
# Django's wsgi file
module          = myproject.wsgi
# the virtualenv (full path)
# home          = /path/to/virtualenv
# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
# the socket (use the full path to be safe)
# socket        = /path/to/your/project/mysite.sock
socket          = :8001
# ... with appropriate permissions - may be needed
# chmod-socket  = 664
# clear environment on exit
vacuum          = true



上面就是来自官网常用的而且非常全的配置,根据需要自行调节即可。现在启动只需如下,
uwsgi --ini myproject_uwsgi.ini
浏览器访问8000,It worked!。
10. mysql安装设置

mysql的安装不多说,
yum install mysql mysql-devel mysql-server
/etc/rc.d/init.d/mysqld start
/usr/bin/mysqladmin -u root password yourpassword
这里我们新建一个用户给django使用。
mysql -u root -p
mysql> create database myprojectdb;
mysql> use mysql;
mysql> insert into user (Host,User,Password) values ('localhost','niger',password('niger'));
mysql> flush privileges;
mysql> grant all privileges on myprojectdb.* to 'niger'@'localhost' identified by 'niger';
11. python3 Django mysql连接及测试

首先安装python和mysql的连接模块,目前就python3,我选择了mysql-connector-python,接下来到myproject目录下设置django的settings.py文件,百度上面真的找不到想找的,谷歌一下问题迎刃而解。
pip install --allow-all-external mysql-connector-python
vim myproject/settings.py
DATABASES = {
'default': {
'ENGINE': 'mysql.connector.django',
'NAME': 'myprojectdb',
'USER': 'niger',
'PASSWORD': 'niger',
}
}
其中database如上设置即可,engine是我们安装的mysql.connector下的django模块,其它看名字就知道意思了。现在来测试下是否成功,
python manage.py migrate
Operations to perform:
Apply all migrations: contenttypes, admin, auth, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying sessions.0001_initial... OK
如上所示说明正常运行(第一次运行会创建一个管理用户,记住),查看数据库如下,
mysql> use myprojectdb;
mysql> show tables;
+----------------------------+
| Tables_in_myprojectdb      |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+
10 rows in set (0.00 sec)
12. 快速搭建blog

我们利用django自带的admin后台来快速搭建一个blog,至于每句代码的意思,写得多了慢慢就知道了,
python manage.py startapp blog
我们发现myproject目录下有了blog文件夹,进入,修改其中的models.py,
vim models.py
from django.db import models
# Create your models here.
class BlogsPost(models.Model):
title = models.CharField(max_length = 150)
body = models.TextField()
tiemstamp = models.DateTimeField()
创建BlogsPost类,继承django.db.models.Model父类,定义三个变量,title (博客标题),body(博客正文),tiemstamp(博客创建时间)(注意我这里time写成tiem了,后面会一直错下去。)
我们要记清楚django这个目录结构,现在回到myproject/myproject/settings.py,加上我们的app:blog,
vim settings.py
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
)
再看myproject/myproject/urls.py,如下,admin这一项要存在,
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'mysite.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
)
再回到blog/models.py,这时将数据添加到admin后台,相应变更
vim models.py
from django.db import models
from django.contrib import admin
# Create your models here.
class BlogsPost(models.Model):
title = models.CharField(max_length = 150)
body = models.TextField()
timestamp = models.DateTimeField()
admin.site.register(BlogsPost)
还记得我们初始过数据库,在相应改变之后要再初始一下,
python manage.py makemigrations
python manage.py migrate
现在就成功变更数据库了。
接下来,启动网站(uwsgi –int myproject_uwsgi.ini,后面就不再附此命令了,当然要保证nginx在运行。)访问http://localhost:8000/admin/,可见登录窗口Django administration,username,password,log in这些,怎么登录,还记得我们创建的用户吗,登录即可。
有样式的话,跳过,没有的话,解决:
右键审查元素或者firebug,调到控制台窗口,刷新页面,发现css错误,点开可见找不到路径,所以导致没有样式加载。我们查看错误,是访问localhost:8000/static/admin/css下的样式,各种查资料,现在用到了我们的static了。在myproject下新建static,然后nginx进行设置,将css代码(请教别人得知在django目录下)转移过来,
mkdir static
vim /etc/nginx/nginx.conf
释放static的注释,并修改
location /static {
alias /你的项目路径/myproject/static; # your Django project's static files - amend as required
}
find / -name django
/usr/share/doc/python-mako-0.3.4/examples/bench/django
/usr/lib/python2.6/site-packages/mysql/connector/django
/usr/local/python3.3/lib/python3.3/site-packages/mysql/connector/django
/usr/local/python3.3/lib/python3.3/site-packages/django
/root/download/mysql-connector-python-2.0.2/lib/mysql/connector/django
/root/download/mysql-connector-python-2.0.2/build/lib/mysql/connector/django
从结果中找符合的,答案很明显,我们去复制下django目录下的文件到我们工程下,你会发现是完全对应的,
[root@localhost myproject]# cp -rf /usr/local/python3.3/lib/python3.3/site-packages/django/contrib/admin/static/admin/ static/
相关目录结构多看看了解下。这时我们重启nginx,启动网站,
/etc/rc.d/init.d/nginx stop
/usr/sbin/nginx -c /etc/nginx/nginx.conf
为什么我要这样停止又那样启动,因为我即使把nginx.conf中user改为root,仍然是各种permission denied,唯独这样不报错。这时访问网站可见样式正常加载了。)
登录之后我们写一篇blog,
发现什么,title,body,tiemstamp(哈哈,故意写错才能说明这是程序中我写的呀),这3个变量是我们在class BlogsPost中定义的不是吗。写完后点击save,会提示The blogs post “BlogsPost object” was added successfully.,怎样,是不是找到一点对应关系了
但是你这个样子,每次都是显示BlogsPost object,不好吧,怎么知道是哪篇文章,于是再来
models.py,
from django.db import models
from django.contrib import admin
# Create your models here.
class BlogsPost(models.Model):
title = models.CharField(max_length = 150)
body = models.TextField()
tiemstamp = models.DateTimeField()
class BlogPostAdmin(admin.ModelAdmin):
list_display = ('title','tiemstamp')

admin.site.register(BlogsPost,BlogPostAdmin)
注意每次代码发生的变化,重启网站后,我们再来到网站同一位置,
so,写错的tiemstamp说明了一切。简单的后端我们处理完了,现在该去看看我们前端如何了。
从Django的角度看,一个页面具有三个典型的组件:
一个模板(template):模板负责把传递进来的信息显示出来。
一个视图(view):视图负责从数据库获取需要显示的信息。
一个URL模式:它负责把收到的请求和你的视图函数匹配,有时候也会向视图传递一些参数。
创建模板
在blog项目下创建templates目录,在目录下创建模板文件archive.html,内容如下:
{% for post in posts %}
<h2>{{ post.title }}</h2>
<p>{{ post.tiemstamp }}</p>
<p>{{ post.body }}</p>
{% endfor%}
设置模板路径,打开myproject/myproject/settings.py文件,在文件底部添加模板路径:
#template
TEMPLATE_DIRS=(
'/你的工程路径/myproject/blog/templates',
)
创建视图函数
打开myproject/blog/views.py文件:
from django.shortcuts import render
from django.template import loader,Context
from django.http import HttpResponse
from blog.models import BlogsPost
# Create your views here.
def archive(request):
posts = BlogsPost.objects.all()
t = loader.get_template("archive.html")
c = Context({'posts':posts})
return HttpResponse(t.render(c))
posts = BlogPost.objects.all() :获取数据库里面所拥有BlogPost对象
t = loader.get_template(“archive.html”):加载模板
c = Context({‘posts’:posts}):模板的渲染的数据是有一个字典类的对象Context提供,这里的是一对键值对。
创建blog的URL模式
在myproject/urls.py文件里添加blog的url:
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'mysite.views.home', name='home'),

url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
)
在myproject/blog/目录下创建urls.py文件:
from django.conf.urls import *
from blog.views import archive
urlpatterns = patterns('',
url(r'^$',archive),
)
之所以在blog应用下面又创建urls.py文件,是为了降低耦合度。这样myproject/urls.py文件针对的是每个项目的url。重启网站,访问http://localhost:8000/blog/,现在可见最简单的页面了。
是不是觉得页面有点单调,怎么调呢?这就要添加样式了。
(css文件统一放在static/admin/css/下,这里内嵌就好了。)
添加样式
在myproject/blog/templates目录里创建base.html的模板:
<html>
<style type="text/css">
body{color:#efd;background:#453;padding:0 5em;margin:0}
h1{padding:2em 1em;background:#675}
h2{color:#bf8;border-top:1px dotted #fff;margin-top:2em}
p{margin:1em 0}
</style>

<body>
<h1>Niger blog</h1>
<h3>From Team Fith4_D3vil</h3>
{% block content %}
{% endblock %}
</body>
</html>
修改archive.html模板,让它引用base.html模板和它的“content”块。
{% extends "base.html" %}
{% block content %}
{% for post in posts %}
<h2>{{  post.title }}</h2>
<p>{{ post.tiemstamp | date:"1,F jS"}}</p>
<p>{{ post.body }}</p>
{% endfor %}
{% endblock %}
再次刷新页面,将看到不一样的风格。
13.pycharm开发

为什么上面要搭建那么复杂的环境,那是因为它是网站发布环境,对于django开发人员来说,上面所做的一切是万万不需要的。只需要一个pycharm,现在pycharm 4.0集成django开发,不管windows下还是linux下,只需要安装python,安装django(甚至不需要,pycharm会自动帮你安装),打开pycharm,默认页面是新建工程,选择django,输入工程名,app名即可。整个django框架自动建成,可直接运行。非常方便。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CentOS Django Python