Python-Flask实战
部署
Python部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| cat/etc/issue python --version python3 --version sudo apt install python3 -pip pip3 --version sudo pip3 install virtualenv sudo mkdir /var/www/html/flask_test sudo chown -R ubuntu/var/www/html/flask_test cd /var/www/html/flask_test
virtualenv -p python3 venv source venv/bin/activate
pip install flask vim run.py python run.py
|
Gunicorn部署
法一:直接启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| pip install gunicore gunicore -w 3 -b 0.0.0.0:9100 run:app
|
法二:配置文件启动
启动配置文件:
1 2 3
| mkdir /var/www/html/flask_test/gunicorn cd /var/www/html/flask_test/gunicorn vim gunicorn_conf.py
|
Python配置文件:
1 2 3 4 5 6 7 8 9
| import multiprocessing bind='0.0.0.0:9100' workers=multiprocessing.cpu_count()*2+1 reload=True loglevel='info' timeout=600 log_path="/tmp/logs/flask_test" accesslog=log_path+'/gunicorn.access.log' errorlog=log_path+'/gunicorn.error.log'
|
终止并加载配置文件启动:
1 2
| pkill gunicorn gunicorn -c
|
Nginx部署
安装
1
| sudo apt-get install nginx
|
基本命令
静态文件配置
进入/etc/nginx/sites-enabled
目录,该目录下所有文件都会被作为配置文件被加载进来。创建文件demo
。
1 2 3 4 5 6 7 8
| server{ location / { root /var/www/html } location /images/ { root /var/www/html/images } }
|
例如访问http://localhost/welcome.html
即为访问/var/www/html/welcome.html
。
然后重新加载:
代理服务器
新建配置文件:
1 2 3 4 5 6 7 8 9 10
| server{ listen 8000; listen [::]:8000; server_name 182.254.163.147; location / { proxy_pass http://182.254.163.147:9100; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
|
Supervisor部署
基本操作
在/home/ubuntu
下新建一个虚拟环境:
1 2 3 4 5
| virtualenv venv source venv/bin/activate pip install supervisor echo_supervisord_conf sudo su - root -c "echo_supervisord_conf > /etc/supervisor/supervisord.conf"
|
将/etc/supervisor
下supervisord.conf
编辑最后一行,以及其他位置作修改:
1 2 3 4 5 6 7 8 9 10 11 12 13
| [include]
files=/etc/supervisor/conf.d/*.ini
[supervisorctl] serverurl=unix://var/run/supervisor.sock
[unix_http_server] file=/var/run/supervisor.sock
[supervisord] logfile=/var/log/supervisord.log pidfile=/var/run/supervisord.pid
|
进入/etc/supervisor/conf.d
编辑test.ini
:
1 2
| [program:foo] command=/bin/cat
|
启动supervisor:
1 2
| sudo supervisord -c /etc/supervisor/supervisor.conf sudo supervisorctl status
|
其他常用supervisorctl命令:
1 2 3 4 5 6 7 8 9 10 11 12 13
| status <name> start <name> stop <name> stop all restart <name> restart all reload 重启远程监督者 reread 重新加载守护程序的配置文件 无需添加删除 add <name> remove <name> update 重新加载配置并添加删除 重启受影响的程序 tail 输出最新log信息 shutdown 关闭supervisord
|
守护Flask
/etc/supervisor/conf.d
下新建配置文件flask_test
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [program:flask_test] command=/var/www/html/flask_test/venv/bin/gunicorn -c gunicorn/gunicorn_conf.py run:app
directory=/var/www/html/flask_test user=root autostart=true autorestart=true
startsecs=10
startretries=3 stdout_logfile=/var/log/flask_test_error.log stderr_logfile=/var/log/flask_test_out.log
stopasgroup=true
stopsignal=QUIT
|
重启:
1 2 3
| sudo supervisorctl reload sudo supervisorctl status sudo pkill gunicorn
|
Flask
基础
1 2 3 4 5 6 7
| from flask import Flask app=Flask(__name__) @app.route('/') def index(): return 'Hello World!' if __name__=='__main__': app.run(debug=True,port=8000)
|
路由
1 2 3 4 5 6 7 8 9 10 11 12 13
| from flask import Flask app=Flask(__name__) @app.route('/') def index(): return 'Hello World!' @app.route('/user/<username>') def show_user_profile(usernname): return f'{username}' @app.route('/post/<int:post_id>') def show_post(post_id): return f'{post_id}' if __name__=='__main__': app.run()
|
构造URL
1 2 3 4 5 6 7 8 9 10
| from flask import Flask,url_for,redirect app=Flask(__name__) @app.route('/post/<int:post_id>') def show_post(post_id): return f'{post_id}' @app.route('/') def index(): return redirect(url_for('show_post',post_id=2)) if __name__=='__main__': app.run()
|
渲染模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="stylesheet" href="/static/css/bootstrap.css"> <script src="/static/js/jquery.js"></script> <script src="/static/js/bootstrap.js"></script> </head> <body> <nav class="navbar navbar-expand-sm bg-primary navbar-dark"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="#">首页</a> </li> <li class="nav-item"> <a class="nav-link" href="#">学员</a> </li> <li class="nav-item"> <a class="nav-link" href="#">图书</a> </li> <li class="nav-item dropdown"> <a class="nav-link dropdonw-toggle" href="#" id="navbardrop" data-toggle="dropdown">关于我们</a> <div class="dropdown-menu"> <a class="dropdown-item" href="#">公司简介</a> <a class="dropdown-item" href="#">企业文化</a> <a class="dropdown-item" href="#">联系我们</a> </div> </li> </ul> </nav> <div class="jumbotron"> <h1 class="display-3">欢迎来到{{name}}</h1> <p> {{message}} </p> <hr class="my-4"> <p> <a class="btn btn-primary btn-lg" href="#" role="button">了解更多</a> </p> </div> </body> <html>
|
使用render_template
渲染:
1 2 3 4 5 6 7 8 9 10 11
| from flask import Flask,url_for,redirect,render_template app=Flask(__name__,template_folder='.') @app.route('/') def index(): name="这是名字" message=""" 这是Message """ return render_template("tmp.html",name=name,message=message) if __name__=='__main__': app.run()
|
模板过滤器
变量过滤器
1 2 3 4
| <p>{{mydict['key']}}</p> <p>{{mylist[2]}}</p> <p>{{mylist[myintvar]}}</p> <p>{{myobj.somemethod()}}</p>
|
内置过滤器
1 2
| <p>{{name|capitalize}}</p>
|
其他常见过滤器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| safe 渲染时不转义 capitalize lower upper title trim striptags 删掉html标签 default(value,default_value=u'',boolean=False) 默认值 别名d escape(s) 转义html 别名e first(seq) 返回序列第一个元素 last(seq) 最后一个 length(object) 返回长度 random(seq) 序列中随机值 max(value,case_sensitive=False,attribute=None) 序列最大值 min(value,case_sensitive=False,attribute=None) 序列最小值 unique(value,case_sensitive=False,attribute=None) 不重复的值 wordcount(s) 单词数 tojson(value,indent=None) 变量值转json truncate(s.length=255,killwords=False,end='...',leeway=None) 截断 length长度 killwords截断单词 end结尾符号
|
自定义过滤器
法一:
1 2 3 4 5
| def count_length(arg): return len(arg) app=Flask(__name__) app.secret_key='xxx' app.add_template_filter(count_length,'count_length')
|
模板:
1
| <div>全文共{{content|count_length}}</div>
|
法二:
1 2 3
| @app.template_filter() def count_length(arg): return len(arg)
|
控制结构
1 2 3 4 5 6 7 8 9 10 11
| {% if user %} Hello, {{user}}! {% else %} Hello, Stranger! {% endif %}
<ul> {% for comment in comments %} <li>{{comment}}</li> {% endfor %} </ul>
|
Session
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @app.route('/') def index(): return render_template('index.html') @app.route('/login',methods=['GET','POST']) def login(): if request.method=='POST': username=request.form['username'] password=request.form['password'] if username=='xxx' and password=='xxx': session['username']=username session['logged_in']=True return redirect(url_for('index')) return render_template('login.html') @app.route('/logout') def logout(): session.clear() return redirect(url_for('login'))
|
HTML模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>用户登录</title> </head> <body> {% if session['logged_in'] %} 欢迎{{session['username']}}登录 {% else %} 请先登录 {% endif %} </body> </html>
|
模板继承
base.html父模板:
1 2 3
| {% include '_nav.html' %} {% block content %} {% endblock %}
|
index.html子模板:
1 2 3 4
| {% extends 'base.html' %} {% block content %}
{% endblock %}
|
消息闪现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from flask import Flask,request,render_template,redirect,url_for,flash app=Flash(__name__) app.secret_key='xxx' @app.route('/login',methods=['GET','POST']) def login(): if request.method=='POST': username=request.form['username'] password=request.form['password'] if username=='xxx' and password=='xxx': flash('登录成功','success') else: flash('用户名或密码错误','error') return redirect(url_for('login')) return render_template('login.html') if __name=='__main__': app.run()
|
HTML模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <head> <style> .error{color:red} .success{color:blue} </style> </head> <body> <div style="padding:20px"> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} <ul class="flashes"> {% for category,message in messages %} <li class="{{category}}">{{message}}</li> {% endfor %} </ul> {% endif %} {% endwith %} </div> </body>
|
自定义错误页面
1 2 3
| @app.errorhandler(404) def page_not_found(e): return render_template('404.html'),404h
|