查看原文
其他

项目实战:使用Python的Flask模块快速开发一个web入门小项目

ikeguang.com 大数据技术派 2022-10-15

平时做数据分析挖掘的结果,难免会需要在Web上展示出来,这样更有逼格。那么,开发web页面难吗?使用Java开发门槛太高,一堆注解绝对让你投降;使用PHP开发,好像太骚了。其实,我们需要有这么一个工具,既能做数据分析挖掘,又能做web展示,非你莫属了——Python。


这里,选择Python的轻量级框架Flask,开发速度更快,开发一个简单的话题发布,支持基本的登陆、注销功能。


项目截图


未登陆前

位登陆前,支持浏览,只读权限,右上角有登陆按钮。

登陆后

登陆后,可以发布主题,可以注销。

可以看到,功能非常简单,这是第一步,有了基础才能自己学习,做出炫酷的分析结果。


项目过程

项目过程,分为以下几步:

  • web服务的第一个请求之前,需要初始化数据库连接;

  • 游客(未登陆状态),可以看到所有话题;

  • 为了简化,只有一个用户硬编码,没有用户表;

  • 登陆之后,可以发布主题,数据保存到数据库;

  • 注销后,回到游客状态;


项目代码结构

这个项目是flask官方入门项目,取名flaskr,工程目录结构如下:


  • flask目录:这里暂且记为项目根目录;

  • static:存放网站静态文件,包括css样式,图片文件等;

  • templates:前端jinja2 html模板文件;

  • entries.db:SQLite3数据文件;

  • flaskr.py:Python项目主要代码文件;

  • schema.sql:建表文件,这里需要一张表,保存用户发布的话题;


最后,会上完整代码,复制过去可以直接运行的。


初始化上下文环境

首先初始化应用和一些变量,包括Flask实例,g对象,如果使用session,需要初始化一个app.secret_key

import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, \
     render_template, flash

app = Flask(__name__, instance_path='D:/我的文件/Codes/PyCode/web/flask/flaskr')
app.config['USERNAME'] = 'name'
app.config['PASSWORD'] = 'password'
app.secret_key = 'ajflafoo8qm.mgaj'

# DATABASE = 'D:/我的文件/Codes/PyCode/web/flask/flaskr/entries.db'
DATABASE = os.path.join(os.getcwd(), 'entries.db')

注意:自己电脑上面执行的时候,D:/我的文件/Codes/PyCode/web/flask/flaskr,这个是我的SQLite3地址,需要换成自己的,对应地址。


初始化数据库

由于是"Hello world"入门项目,这里使用的数据库是小型的磁盘型数据库SQLite3,没必要连接大型数据库。


SQLite3何许人也?

SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。


连接数据库,需要获取数据库连接,SQLite3数据库不错在,则会新建一个文件夹,名字为数据库名:

def get_db():
    """connect to special database"""
    return sqlite3.connect(DATABASE)


第一次运行需要初始化数据库和表,调用init_table方法即可。

def init_table():
    """first run create table"""
    db = get_db()
    result = db.cursor().execute(
        "SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = 'entries'").fetchall()
    table_exists = result[0][0] == 1

    # 不存在,则创建表
    if not table_exists:
        with app.open_resource('schema.sql', mode='r'as f:
            db.cursor().executescript(f.read())
        db.commit()
    else:
        print('entries already exists .')

    db.close()


每一个请求之前@app.before_request需要连接数据库,request请求之后@app.teardown_request关闭数据库:

@app.before_request
def before_request():
    g.db = get_db()


@app.teardown_request
def teardown_request(exception):
    if hasattr(g, 'db'):
        g.db.close()


用户登陆、注销

通常,用户登陆后,才有权限发表话题,注销后就是游客身份,只能看,不能发布话题。

显示所有发布的话题

@app.route('/')
def show_entries():
    """显示条目"""
    sql = 'select title, text from entries order by id desc'
    cursor = g.db.cursor()
    entries = [dict(title = row[0], text = row[1]) for row in cursor.execute(sql).fetchall()]
    cursor.close()
    return render_template('show_entries.html', entries = entries)


用户登陆

为了简单起见,没有建用户表,只是在内存中定义了一个用户,用户名:name,密码:password。

@app.route('/login', methods=['GET', 'POST'])
def login():
    """登陆函数"""
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            flash('You were logged in')
            return redirect(url_for('show_entries'))
    return render_template('login.html', error = error)


用户注销

注销后,直接重定向到主页。

@app.route('/logout')
def logout():
    """注销函数"""
    session.pop('logged_in'None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))


登陆用户发布话题

用户登陆后,可以发布话题,内容存在SQLite3数据库里面,用户每次刷新或者跳转到主页需要读取数据库,显示。通过表单发送数据,methods是POST。

@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    sql = 'insert into entries(title, text) values(?, ?)'
    g.db.execute(sql, [request.form['title'], request.form['text']])
    g.db.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('show_entries'))


项目完整代码

完整代码,这里还是贴出来吧,虽然不太美观,确保Python3已经安装了flask模块,否则通过pip3 install flask命令即可安装 ,代码可以直接执行

flaskr.py

这里是主要逻辑代码。

import os
import sqlite3
from flask import Flask, request, session, g, redirect, url_for, abort, \
     render_template, flash

app = Flask(__name__, instance_path='D:/我的文件/Codes/PyCode/web/flask/flaskr')
app.config['USERNAME'] = 'name'
app.config['PASSWORD'] = 'password'
app.secret_key = 'ajflafoo8qm.mgaj'

# DATABASE = 'D:/我的文件/Codes/PyCode/web/flask/flaskr/entries.db'
DATABASE = os.path.join(os.getcwd(), 'entries.db')


def init_table():
    """first run create table"""
    db = get_db()
    result = db.cursor().execute(
        "SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = 'entries'").fetchall()
    table_exists = result[0][0] == 1

    # 不存在,则创建表
    if not table_exists:
        with app.open_resource('schema.sql', mode='r'as f:
            db.cursor().executescript(f.read())
        db.commit()
    else:
        print('entries already exists .')

    db.close()


def get_db():
    """connect to special database"""
    return sqlite3.connect(DATABASE)


"""
@app.before_request
def get_connection():
    db = getattr(g, 'db', None)
    if db is None:
        db = g.db = get_db()
        with app.open_resource('schema.sql', mode='r') as f:
            db.cursor().executescript(f.read())
        db.commit()
"""



@app.before_request
def before_request():
    g.db = get_db()


@app.teardown_request
def teardown_request(exception):
    if hasattr(g, 'db'):
        g.db.close()


@app.route('/')
def show_entries():
    """显示条目"""
    sql = 'select title, text from entries order by id desc'
    cursor = g.db.cursor()
    entries = [dict(title = row[0], text = row[1]) for row in cursor.execute(sql).fetchall()]
    cursor.close()
    return render_template('show_entries.html', entries = entries)


@app.route('/add', methods=['POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    sql = 'insert into entries(title, text) values(?, ?)'
    g.db.execute(sql, [request.form['title'], request.form['text']])
    g.db.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('show_entries'))


@app.route('/login', methods=['GET', 'POST'])
def login():
    """登陆函数"""
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            flash('You were logged in')
            return redirect(url_for('show_entries'))
    return render_template('login.html', error = error)


@app.route('/logout')
def logout():
    """注销函数"""
    session.pop('logged_in'None)
    flash('You were logged out')
    return redirect(url_for('show_entries'))


if __name__ == '__main__':
    # 第一次执行,需要初始化数据库,和表
    init_table()

    app.run(debug=True)


还有前端代码,就不贴出来了,完整项目已经上传到Github,点击阅读原文也可以,地址:

https://github.com/ddxygq/PyCode/tree/master/web/flask/flaskr

Github代码下载下来,可以直接执行的。



猜你可能喜欢

堆排序算法

markdown纯手撸复杂数学公式

Python爬虫解析库——BeautifulSoup4(美丽的汤)

程序员必备的一些数学基础知识


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存