zoukankan      html  css  js  c++  java
  • Django: 之Apache、Nginx部署以及发送邮件

    在这里讲述部署的方法和常见的问题,并给出了在BAE,JAE,SAE等上面部署的实例。

    Django + nginx + Gunicorn/uwsgi部署方式,参见另一篇:Django部署(nginx)

    如果是自己的服务器(比如阿里云的或者自己搭建的虚拟机)请看下文:

    如果你是新手,个人推荐你用Ubuntu,除非你对Linux非常熟悉,Ubuntu服务器的优点:

    一、开机apache2等都自动启动,不需要额外设置

    二、安装软件非常方便apt-get搞定

    三、安装ssh,git等也非常容易,几乎是傻瓜化

    可以先用用Linux Mint,它用起来更简单,和ubuntu兼容。

    下面是Ubuntu上部署详细步骤:

    1、安装apache2和mod_wsgi

    wulaoer@wulaoer:~$sudo apt-get install apache2
     
    # Python 2
    wulaoer@wulaoer:~$ sudo apt-get install libapache2-mod-wsgi
     
    # Python 3
    wulaoer@wulaoer:~$sudo apt-get install libapache2-mod-wsgi-py3
    

    2、确认安装的apache2版本号

    wulaoer@wulaoer:~$ apache2 -v
    Server version: Apache/2.4.12 (Ubuntu)
    Server built:   Jul 24 2015 15:59:00
    

    3、准备一个新网站

    wulaoer@wulaoer:~$ sudo vi /etc/apache2/sites-available/sitename.conf
    sudo: 无法解析主机:wulaoer
    <VirtualHost *:80>
        ServerName www.yourdomain.com
        ServerAlias otherdomain.com
        ServerAdmin wulaoer@163.com
    
        Alias /media/ /home/tu/blog/media/
        Alias /static/ /home/tu/blog/static/
    
        <Directory /home/tu/blog/media>
            Order deny,allow
    
            Allow from all
    </Directory>
    
        <Directory /home/tu/blog/static>
            Require all granted
        </Directory>
    
        WSGIScriptAlias / /home/tu/blog/blog/wsgi.py
        # WSGIDaemonProcess ziqiangxuetang.com python-path=/home/tu/blog:/home/tu/.virtualenvs/blog/lib/python2.7/site-packages
        # WSGIProcessGroup ziqiangxuetang.com
    
        <Directory /home/tu/blog/blog>
        <Files wsgi.py>
            Require all granted
        </Files>
        </Directory>
    </VirtualHost>
    

    如果你的apache的版本号是 2.2.x

    用下面的代替 Require all granted

    Order deny,allow
    Allow from all
    

    备注:把上面配置的文件中这两句的备注去掉,可以使用virtualenv来部署网站,当然也可以只写一个/home/tu/blog

        # WSGIDaemonProcess ziqiangxuetang.com python-path=/home/tu/blog:/home/tu/.virtualenvs/blog/lib/python2.7/site-packages
        # WSGIProcessGroup ziqiangxuetang.com
    

    4、修改wsgi.py文件

    注意:上面如果写了WSGIDaemonProcess 的话,这一步可以跳过,即可以不修改 wsgi.py 文件。 

    上面的配置中写的WSGIScriptAlias / /home/tu/blog/blog/wsgi.py

    就是把apache2和你的网站project联系起来了

    import os
    from os.path import join,dirname,abspath
     
    PROJECT_DIR = dirname(dirname(abspath(__file__)))#3
    import sys # 4
    sys.path.insert(0,PROJECT_DIR) # 5
     
    os.environ["DJANGO_SETTINGS_MODULE"] = "blog.settings" # 7
     
    from django.core.wsgi import get_wsgi_application
    application = get_wsgi_application()
    

    第3、4、5行为新加内容,作用是让脚本找到django项目的位置,也可以在sitename.conf中做,用WSGIPythonPath,想连接的自行搜索,第7行如果一台服务器有多个django project时一定要修改成上面那样,否则访问的时候会发生网站互相串的情况,即访问A网站到了B网站,一会正常,一会不正常(当然可以使用mod_wsgi daemon模式,点击这里

    5、设置目录和文件权限

    一般目录权限设置为755,文件权限设置为644

    假如项目位置在/home/tu/wulaoer(在wulaoer下面有一个manage.py,wulaoer是项目名称)

    cd /home/tu/
    sudo chmod -R 644 wulaoer
    sudo find wulaoer -type d -exec chmod 755 {} ;
    

    上传文件夹权限

    media文件夹一般用来存放用户上传文件,static一般用来放自己网站的js,css,图片等,在settings.py中的相关设置

    STATIC_URL为静态文件的网址STATIC_ROOT为静态文件的根目录,

    MEDIA_URL为用户上传文件夹的根目录,MEDIA_URL为对应的访问网址

    在settings.py中设置:

    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/dev/howto/static-files/
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR,'static')
     
    # upload folder
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR,'media')
    

    在Linux服务器上,用户上传目录还要设置给www-data用户的写权限,下面的方法比较好,不影响原来的用户编辑。

    假如上传目录为wulaoer/media/uploads文件夹,进入media文件夹,将uploads用户组改为www-data,并且赋予改组写权限:

    cd media/ # 进入media文件夹
    sudo chgrp -R www-data uploads
    sudo chmod -R g+w uploads
    

    备注:这两条命令,比直接用sudo chown -R www-data:www-data uploads好,因为下面的命令不影响文件原来所属用户编辑文件,fedora系统应该不用设置上面的权限,但是个人强烈推荐用ubuntu,除非你对linux非常熟悉,你自己可以选择。

    如果你是一段氏sqlite3数据库,还会提示Attempt to write a readonly database,同样要给www-data写数据库的权限

    进入项目目录的上一级,比如project目录为/home/tu/wulaoer哪就进入/home/tu执行下面的命令(和修改上传文件类似)

    sudo chgrp www-data blog
    sudo chmod g+w blog
    sudo chgrp www-data blog/db.sqlite3  # 更改为你的数据库名称
    sudo chmod g+w blog/db.sqlite3
    

    备注:上面的不要加-R,-R是更改包括所有的子文件夹和文件,这样不安全。个人建议可以专门弄一个文件夹,用它来放sqlite3数据库,给该文件夹www-data写权限,而不是整个项目给写权限,有些文件只要读懂权限就够了,给写权限会造成不安全。

    6、激活新网站

    sudo a2ensite sitename 或 sudo a2ensite sitename.conf
    

    如果顺利,这样网站就搭建成功了,访问你的网址试试看,如果发现问题就接着看下面的。

    7、错误排查

    一、没有静态文件,网站打开很乱,没有布局,多半是静态文件没有生效。

    1、确保你的配置文件中的路径是正确的

    2、确保你的settings.py中的文件设置正确

    3、收集静态文件

    python manage.py collectstatic
    

    二、网站打开后报错

    这时你可以把settings.py更改

    DEBUG = True
    

    重启服务器

    sudo service apache2 restart
    

    再访问网站来查看具体的出错信息。

    如果这样做还看不到出错信息,只是显示一个服务器错误,你可以查看apache2的错误日志

    cat /var/log/apache2/error.log
    

    根据错误日志里面的内容进行修改!

    总结:

    部署时文件对应关系:

    sitename.conf ---> wsgi.py---> settings.py----> urls.py ----> views.py

    扩展

    明白了上面的关系,一个Django project使用多个域名或让app使用子域名很简单,只要新建wsgi.py文件,更改里面对应的settings文件,新的settings文件可以对应新的urls.py,从而做到访问与原来不同的地址!

    Django 部署(Nginx)

    1、运行开发服务器测试

    cd wulaoer # 进入项目 wulaoer 目录
    python manage.py runserver
    

    2、安装nginx和需要的包

    2.1 安装nginx等软件

    ubuntu/Linux Mint等,下面简写为(ubuntu):

    sudo apt-get install python-dev nginx
    

    centos/Fedora/redhat等,下面简写为(centos)

    sudo yum install epel-release
    sudo yum install python-devel nginx
    

    2.2安装supervisor,一个专门用来管理进程的工具,我们用它来管理gunicorn/uwsgi

    sudo pip install supervisor
    

    Ubuntu用户,请直接看3,一下是Centos注意事项:

    Centos下,如果不是非常懂SELinux和iptables的话,为了方便调试,可以先临时关闭它们,如果发现部署了之后出不来结果,可以临时关闭测试一下,这样就知道是不是SELinux和iptables的问题

    CentOS 7 iptables如何使用http://stackoverflow.com/questions/24756240/

    将SELinux设置为宽容模式,方便调试:

    sudo setenforce 0
    

    防火墙相关的设置:

    可以选择临时关闭防火墙
    sudo service iptables stop
     
    或者开放一些需要的端口,比如 80
    sudo iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
    

    上面的两条命令,如果是Centos 7 用

    临时关闭防火墙
    sudo systemctl stop firewalld
     
    或者 开放需要的端口
    sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
    sudo firewall-cmd --reload
    

    备注:由于我们还没有用最新版的Fedora, 新版Fedora需要用dnf来安装包,需求的同学自测,可以参考这里

    3、使用gunicorn/uwsgi来部署(二选一)

    注意:以下为二选一,不需要两个都用

    3.1使用gunicorn(纯Python实现的包):

    sudo pip install gunicorn
    

    在项目目录下运行下面的命令进行测试:

    gunicorn -w4 -b0.0.0.0:8001 wulaoer.wsgi
    

    -w表示开启多少个worker,-b表示要使用的ip和port,我们这里用的是8001,0.0.0.0代表监控电脑的所有ip。

    如果使用了virtualenv可以这样

    /path/to/env/bin/gunicorn --chdir /path/to/project --pythonpath /path/to/env/ -w4 -b0.0.0.0:8017 project.wsgi:application
    

    用--pythonpath指定依赖包路径,多个点时候用逗号,隔开,如:'/path/to/lib,/home/tu/lib'

    3.2使用uwsgi(纯C 语音实现的包):

    安装uwsgi

    sudo pip install uwsgi
    

    使用uwsgi运行项目

    uwsgi --http :8001 --chdir /path/to/project --home=/path/to/env --module project.wsgi
    

    这样就可以跑了,  --home指定virtualenv路径,如果没有可以去掉。project.wsgi指project/wsgi.py文件

    如果端口提示已经被占用:

    probably another instance of uWSGI is running on the same address (:8002).
    bind(): Address already in use [core/socket.c line 764]
    

    这时可用把相关的进程kill掉:

    按照端口进行查询:

    lsof -i :8002
    

    可用查出:

    COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
    uwsgi   2208   tu    4u  IPv4 0x53492abadb5c9659      0t0  TCP *:teradataordbms (LISTEN)
    uwsgi   2209   tu    4u  IPv4 0x53492abadb5c9659      0t0  TCP *:teradataordbms (LISTEN)
    

    这时根据PID可以用下面的命令kill掉相关的程序:

    sudo kill -9 2208 2209
    

    按照程序名称查询:

    ps aux | grep uwsgi
    

    4、使用supervisor来管理进程

    安装supervisor软件包

    (sudo) pip install supervisor
    

    生成supervisor默认配置文件,比如我们放在/etc/supervisord.conf路径中:

    (sudo) echo_supervisord_conf > /etc/supervisord.conf
    

    打开supervisor.conf在最底部添加(每行前面不要有空格,防止报错):

    [program:wulaoer]
    command=/path/to/uwsgi --http :8003 --chdir /path/to/wulaoer --module wulaoer.wsgi
    directory=/path/to/wulaoer
    startsecs=0
    stopwaitsecs=0
    autostart=true
    autorestart=true
    

    command中写上对应的命令,这样,就可以用supervisor来管理来。

    启动supervisor

    (sudo) supervisord -c /etc/supervisord.conf
    

    重启wulaoer程序(项目):

    (sudo) supervisorctl -c /etc/supervisord.conf restart wulaoer
    

    启动,停止,或重启supervisor管理的某个程序或所有程序:

    (sudo) supervisorctl -c /etc/supervisord.conf [start|stop|restart] [program-name|all]
    

    以uwsgi为例,上面这样使用一行命令太长了,我们是一ini配置文件来搞定,比如项目在/home/tu/wulaoer这个位置。

    在其中新建一个uwsgi.ini全路径为/home/tu/wulaoer/uwsgi.ini

    [uwsgi]
    socket = /tmp/wulaoer.sock
    chdir=/home/tu/wulaoer
    wsgi-file = zqxt/wsgi.py
    touch-reload=/home/tu/wulaoer/reload
     
    processes = 2
    threads = 4
     
    chmod-socket = 664
    chown-socket=tu:www-data
    

    注意上面的/tmp/wulaoer.sock,一会我们把它和nginx关联起来。

    在项目上新建一个空白的reload文件,只要touch一下这个文件(touch reload)项目就会重启。

    修改supervisor配置文件中的command一行:

    [program:wulaoer]
    command=/path/to/uwsgi --ini /home/tu/wulaoer/uwsgi.ini
    directory=/path/to/wulaoer
    startsecs=0
    

    然后重启一下supervisor:

    (sudo) supervisorctl -c /etc/supervisord.conf restart wulaoer
    或者
    (sudo) supervisorctl -c /etc/supervisord.conf restart all
    

    5、配置nginx

    新建一个网站wulaoer

    sudo vim /etc/nginx/sites-available/wulaoer.conf
    

    写入一下内容

    server {
        listen      80;
        server_name www.wulaoer.org;
        charset     utf-8;
     
        client_max_body_size 75M;
     
        location /media  {
            alias /path/to/project/media;
        }
     
        location /static {
            alias /path/to/project/static;
        }
     
        location / {
            uwsgi_pass  unix:///tmp/wulaoer..sock;
            include     /etc/nginx/uwsgi_params;
        }
    }
    

    激活网站:

    sudo ln -s /etc/nginx/sites-available/zqxt.conf /etc/nginx/sites-enabled/wulaoer.conf
    

    测试配置语法问题

    sudo service nginx configtest
    

    重启nginx服务器:

    sudo service nginx reload 或者 sudo service nginx restart
    

    一些有用的参考教程:

    Django 官网部署教程:

    https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/gunicorn/

    https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/uwsgi/

    一些博客相关教程:

    http://www.ituring.com.cn/article/201045

    http://www.jianshu.com/p/be9dd421fb8d

    http://blog.csdn.net/tengzhaorong/article/details/12833157

    nginx 与 socket

    http://uwsgi-docs.readthedocs.org/en/latest/tutorials/Django_and_nginx.html#configure-nginx-for-your-site

    防火墙:

    iptables: https://www.digitalocean.com/community/tutorials/how-to-setup-a-basic-ip-tables-configuration-on-centos-6

    centos 7 FireWalld: http://stackoverflow.com/questions/24756240/how-can-i-use-iptables-on-centos-7

    ubuntu ufw 防火墙:http://wiki.ubuntu.org.cn/Ufw%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97

    uwsgi ini 配置文件:http://uwsgi-docs.readthedocs.org/en/latest/tutorials/Django_and_nginx.html#configuring-uwsgi-to-run-with-a-ini-file

    Django 发送邮件

    我们常常会用到一些发送邮件的功能,比如有人提交了应聘的表单,可以向HR的邮箱发送邮件,这样HR不看网站就可以知道有人在网站上提交了应聘信息。

    1、配置相关参数

    如果用的是阿里云的企业邮箱,则类似于下面:

    在settings.py的最后面加上这些

    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
      
    EMAIL_USE_TLS = False
    EMAIL_HOST = 'smtp.wulaoer.org'
    EMAIL_PORT = 25
    EMAIL_HOST_USER = 'mail@wulaoer.org'
    EMAIL_HOST_PASSWORD = 'xxxx'
    DEFAULT_FROM_EMAIL = 'mail@wulaoer.org'
    

    DEFAULT_FROM_EMAIL 还可以写成这样:

    DEFAULT_FROM_EMAIL = 'wulaoer <wulaoer@163.com>'
    

    这样别人收到的邮件就会有你设定的名称,如下:

    发件人:wulaoer <wulaoer@163.com>
    

    下面是一些常用的邮箱:

    163邮箱  126邮箱  QQ邮箱

    其他邮箱参数可能登陆邮箱看帮助信息,也可以尝试在搜索引擎中搜索:“SMTP 邮箱名称”,比如:“163 SMTP” 进行查找。

    2、发送邮件

    2.1官网的一个例子:

    from django.core.mail import send_mail
     
    send_mail('Subject here', 'Here is the message.', 'from@example.com',
        ['to@example.com'], fail_silently=False)
    

    2.2 一次性发送多个邮件:

    from django.core.mail import send_mass_mail
     
     
    message1 = ('Subject here', 'Here is the message', 'from@example.com', ['first@example.com', 'other@example.com'])
    message2 = ('Another Subject', 'Here is another message', 'from@example.com', ['second@test.com'])
    

    备注:send_mail每次发送邮件都会建立一个连接,发送多封邮件时建立多个连接。而send_mass_mail是建立单个连接发送多封邮件,所以一次性发送多封邮件时send_mass_mail要优与send_mail。

    2.3 如果我们想在邮件中添加附件,发送html格式的内容

    from django.conf import settings
    from django.core.mail import EmailMultiAlternatives
     
     
    from_email = settings.DEFAULT_FROM_EMAIL
    # subject 主题 content 内容 to_addr 是一个列表,发送给哪些人
    msg = EmailMultiAlternatives(subject, content, from_email, [to_addr])
     
    msg.content_subtype = "html"
     
    # 添加附件(可选)
    msg.attach_file('./twz.pdf')
     
    # 发送
    msg.send()
    

    上面的做法可能有一些风险,除非你确定你的接收者都可以阅读html格式的邮件。

    为了安全起见,你可以弄两个版本,一个纯文本(text/plain)的为默认的,另外在提供一个html版本的(好像好多国外发送的邮件都是纯文本的)

    from __future__ import unicode_literals
     
    from django.conf import settings
    from django.core.mail import EmailMultiAlternatives
     
    subject = '来自吴老二的问候'
     
    text_content = '这是一封重要的邮件.'
     
    html_content = '<p>这是一封<strong>重要的</strong>邮件.</p>'
     
    msg = EmailMultiAlternatives(subject, text_content, from_email, [to@youemail.com])
     
    msg.attach_alternative(html_content, "text/html")
     
    msg.send()
    

      

  • 相关阅读:
    Django auth组件
    Django 中间件实现用户认证与IP频率限制
    Django 中间件
    Django forms组件
    Django Cookie于Session
    Django分页器
    flask之route中的参数
    Flask之endpoint错误View function mapping is overwriting an existing endpoint function: ***
    Centos6.5 安装python2.7.14
    发布django项目
  • 原文地址:https://www.cnblogs.com/wulaoer/p/5289743.html
Copyright © 2011-2022 走看看