Python | 基于Flask框架开发在线问答社区(一)

本教程也是作者自学flask框架时的笔记,将随着本人的学习过程持续更新,直至搭建起一个类似于知乎的在线问答社区。
本文主要介绍flask框架的基本使用。

Flask简介

Flask是一个使用 Python 编写的__轻量级 Web 应用框架__。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。Flask也被称为 “microframework”,即微框架 ,因为它使用简单的核心,用 extension 增加其他功能。

Flask的安装

pip install flask

关于flask的具体安装教程,可以向国内知名搜索信息服务提供商baidu.com发起业务咨询。(自行百度安装

Linux环境下的配置与运行

export FLASK_APP={python文件}
export FLASK_ENV={development/production}
flask run

Windows环境下的配置与运行

在代码中加入以下代码:

if __name__ == '__main__':  
    app.run()  

动态路由的类型

@app.route('/user/<username>')
def show_user_profile(username):
    # 显示用户名
    return 'User {}'.format(username)

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # 显示提交整型的用户"id"的结果,注意"int"是将输入的字符串形式转换为整型数据
    return 'Post {}'.format(post_id)

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    # 显示 /path/ 之后的路径名
    return 'Subpath {}'.format(subpath)

#路由路径后带不带/的区别
@app.route('/projects/')
def projects():
    return 'The project page'
#说明:重路由链接带/,访问 url/projects 和 url/projects/ 都不会出错

@app.route('/about')
def about():
    return 'The about page'
#说明:重路由不带链接/,访问 url/about 没问题,但是访问 url/about/ 会报Not Found

#HTTP方法的区别
@app.route('/login', methods=['GET', 'POST'])
#可以用methods方法指定http方法,例如GET,POST,HEAD,PUT
def login():
    if request.method == 'POST':
        do_the_login()   # 如果是 POST 方法就执行登录操作
    else:
        show_the_login_form()   # 如果是 GET 方法就展示登录表单
类型含义
string默认的数据类型,接受没有任何斜杠“/”的字符串
int接受整型
float接受浮点类型
path和 string 类似,但是接受斜杠“/”
uuid只接受 uuid 字符串

可以用__<type:varname>__来指定路由的类型

静态文件渲染与模板

from flask import Flask, render_template
app = Flask(__name__)

#该代码说明,可以使用多个route
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):   # 默认 name 为 None
    return render_template('hello.html', name=name)   # 将 name 参数传递到模板变量中

其中文件的布局hello.csshello.html文件存放的位置如下:

/hello.py
/templates
    /hello.html
/static
    /hello.css

也即,html文件应该存放在templates,而css文件应该存放在static文件中。
其中html文件中是可以写一些简单的代码,如同jsp
如下:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}   <!-- 如果 name 不为空则将 name 渲染出来 -->
  <h1>Hello {{ name }}!</h1>
{% else %}   <!-- 如果 name 为空则打印 Hello World! -->
  <h1>Hello World!</h1>
{% endif %}

代码用{% xxx %}来装起来

请求对象

使用request可以访问请求对象的内容

from flask import request
@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # 当请求形式为“GET”或者认证失败则执行以下代码
    return render_template('login.html', error=error)
#使用如下代码可以获取get方法中的参数?value=xxxxx 
searchword = request.args.get('key', '')

文件上传

from flask import request
from werkzeug import secure_filename
#此命令可以配置文件上传的位置
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
#使用secure_filename避免出现安全问题

Cookies

注意:如果你要使用会话(sessions),请不要直接使用 cookies,相反,请用 Flask 中的会话,因为Flask 已经在cookies 上增加了一些安全细节;

读取cookies

关键代码

request.cookies.get('cookies_name')

示例

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # 注意这里引用cookies字典的键值对是使用cookies.get(key)
    # 而不是cookies[key],这是防止该字典不存在时报错"keyerror"
存储cookies

示例:

from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

综合示例:

@app.route('/index')
def index():
	username=request.cookies.get('username')
	if username==None:
		resp = make_response("Hello Eric")
		resp.set_cookie('username', 'Eric')
		return resp
	else:
		return username

重定向

from flask import Flask
from flask import abort, redirect, url_for

app = Flask(__name__)

@app.route('/')
def index():
    #redirect() 命令可以得到重定向,利用url_for函数得到的login函数的路由地址
    return redirect(url_for('login'))

@app.route('/baidu')
def baidu():
    #也可以直接重路由到一个http地址中
    return redirect("http://www.baidu.com")

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

装饰器

from flask import render_template


#装饰了error401的返回界面
@app.errorhandler(401)
def page_not_found(error):
    return render_template('page_not_found.html'), 404#函数末尾带有响应值,404就是页面没有找到,如果不写就是默认200

会话

首先需要简单介绍一下会话的机制

​ Session主要可以实现会话身份识别。首先,用户端向服务端发送一个请求,服务端接收到请求后,初始化会话,生成相应的会话信息,核心是会话ID,把会话ID发送给客户端,客户端接收到这个会话ID,把它存储起来,下一次发送请求的时候,附带着这个会话ID一起发送给服务端,服务端只要根据这个会话ID,就知道是谁了。这个会话ID,就像我们的身份证号码,一直伴随终生。客户端的会话ID可以通过Cookies来存储,也可能存储在url中,但这不安全

  • 利用flask框架使用会话需要设置secret_key
from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)

# 设置密钥,保证会话安全
# 会话安全的关键在于有一个好的密匙
app.secret_key = '_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # 如果用户名存在,则从会话中移除该用户名
    session.pop('username', None)
    return redirect(url_for('index'))

消息闪烁:flash

Flask 提供了一个真正的简单的方式来通过消息闪现系统给用户反馈。消息闪现系统基本上使得在请求结束时记录信息并在下一个 (且仅在下一个)请求中访问。通常结合模板布局来显示消息。
使用flash()方法来闪现一个消息,使用get_flashed_messages()能够获取消息,get_flashed_messages()也能用于模板中。

from flask import Flask, flash, redirect, render_template, \
     request, url_for

app = Flask(__name__)
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != 'admin' or \
                request.form['password'] != 'secret':
            error = 'Invalid credentials'
        else:
            flash('You were successfully logged in')
            return redirect(url_for('index'))
    return render_template('login.html', error=error)

(未完待续)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐