欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Flask入门之完整项目搭建

程序员文章站 2022-05-14 08:44:57
一、创建虚拟环境 1,新建虚拟环境 cmd中输入:mkvirtualenv 环境名 2,在虚拟环境安装项目运行所需要的基本模块 二、构建项目文件目录 三、配置文件 settings/__init__.py: settings/dev.py: settings/prop.py: 四、项目主应用初始化项 ......

  一、创建虚拟环境

  1,新建虚拟环境

  cmd中输入:mkvirtualenv 环境名

  2,在虚拟环境安装项目运行所需要的基本模块

pip install flask==0.12.4
pip install redis
pip install flask-session
pip install flask-script
pip install flask-mysqldb
pip install flask-sqlalchemy
pip install flask-migrate
pip install flask_wtf

  二、构建项目文件目录

项目根目录/
├── application/            # 项目主要逻辑代码保存目录
|    ├── apps               #存放蓝图
|    ├── settings/          # 项目配置存储目录
│    │   ├ dev.py           # 开发阶段的配置文件
│    │   ├ prop.py          # 生产阶段的配置文件
|    ├──templates           #存放全局的html文件
│    ├── __init__.py        # 项目初始化文件
├── manage.py               # 项目的终端管理脚本文件
├──logs/                    #存放日志文件
├──docs/                    #存放文档文件

Flask入门之完整项目搭建

  三、配置文件

  settings/__init__.py:

from redis import strictredis

class config(object):
    """项目配置核心类"""
    # 调试模式
    debug = true

    # todo 配置日志
    pass

    # mysql数据库的配置信息
    sqlalchemy_database_uri = "mysql://root:mysql@127.0.0.1:3306/students?charset=utf8"
    # 动态追踪修改设置,如未设置只会提示警告
    sqlalchemy_track_modifications = false
    # 查询时会显示原始sql语句
    sqlalchemy_echo= false

    # 配置redis
    redis_host = '127.0.0.1'  # 项目上线以后,这个地址就会被替换成真实ip地址,mysql也是
    redis_port = 6379

    # 设置密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串
    secret_key = "ghhbljaa0uzw2aflqjoxrukore4blkty/1vamudh6opq3uwgytsduyxch62aw3ju"

    # flask_session的配置信息
    session_type = "redis" # 指定 session 保存到 redis 中
    session_use_signer = true # 让 cookie 中的 session_id 被加密签名处理
    session_redis = strictredis(host=redis_host, port=redis_port,db=1) # 使用 redis 的实例
    permanent_session_lifetime = 24 * 60 * 60 # session 的有效期,单位是秒

  settings/dev.py:

from . import config
class developementconfig(config):
    """开发模式下的配置"""
    # 查询时会显示原始sql语句
    sqlalchemy_echo= true

  settings/prop.py:

from . import config
class productionconfig(config):
    """生产模式下的配置"""
    debug = false

  四、项目主应用初始化项目

  application/__init__.py,创建flask应用并加载配置

from flask import flask
from application.settings.dev import developementconfig
from application.settings.prop import productionconfig

config = {
    "dev": developementconfig,
    "prop": productionconfig,
}

def init_app(config_name):
    """项目的初始化函数"""
    app = flask(__name__)

    # 设置配置类
    config = config[config_name]

    # 加载配置
    app.config.from_object(config)

    return app

  manage.pyz中调用init_app函数,启动项目

from application import init_app

app = init_app("dev")

@app.route("/")
def index():
    return "index"

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

  在application/__init__.py项目初始化文件中加载redis或者mysql的初始化代码

from flask import flask
from redis import strictredis
from flask_wtf.csrf import csrfprotect
from flask_session import session

from application.settings.dev import developementconfig
from application.settings.prop import productionconfig

config = {
    "dev": developementconfig,
    "prop": productionconfig,
}

# 为了方便redis的连接对象在函数外部可以使用,预先设置一个全局变量,接下来在函数中用于保存redis的连接
redis_store = none

def init_app(config_name):
    """项目的初始化功能"""
    app = flask(__name__)

    # 设置配置类
    config = config[config_name]

    # 加载配置
    app.config.from_object(config)

    # redis的链接初始化
    global redis_store
    redis_store = strictredis(host=config.redis_host, port=config.redis_port,db=0)

    # 开启csrf防范功能
    csrfprotect(app)

    # 开启session功能
    session(app)

    # todo 注册蓝图对象到app应用中

    return app

  五、增加数据库配置

  application/__init__.py增加代码

# from flask import flask
# from redis import strictredis
# from flask_wtf.csrf import csrfprotect
# from flask_session import session
from flask_sqlalchemy import sqlalchemy
# 
# from application.settings.dev import developementconfig
# from application.settings.prop import productionconfig
# 
# config = {
#     "dev": developementconfig,
#     "prop": productionconfig,
# }
# 
# # 为了方便redis的连接对象在函数外部可以使用,预先设置一个全局变量,接下来在函数中用于保存redis的连接
# redis_store = none
db = sqlalchemy()
# 
# def init_app(config_name):
#     """项目的初始化功能"""
#     app = flask(__name__)
# 
#     # 设置配置类
#     config = config[config_name]
# 
#     # 加载配置
#     app.config.from_object(config)
# 
#     # redis的链接初始化
#     global redis_store
#     redis_store = strictredis(host=config.redis_host, port=config.redis_port,db=0)
# 
#     # 开启csrf防范功能
#     csrfprotect(app)
# 
#     # 开启session功能
#     session(app)
# 
    # 配置数据库链接
    db.init_app(app)
# 
#     # todo 注册蓝图对象到app应用中
# 
#     return app

  六、在manage启动文件中新增关于启动过程中的相关功能

  manage.py

from application import init_app,db
from flask_script import manager
from flask_migrate import migrate, migratecommand

app = init_app("dev")

# 使用终端脚本工具启动和管理flask
manager = manager(app)

# 启用数据迁移工具
migrate(app, db)
# 添加数据迁移的命令到终端脚本工具中
manager.add_command('db', migratecommand)


@app.route("/")
def index():
    return "index"

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

  七、日志

  application/__init__.py

import logging
from logging.handlers import rotatingfilehandler

# 把日志相关的配置封装成一个日志初始化函数
def setup_log(config):
    # 设置日志的记录等级
    logging.basicconfig(level=config.log_level)  # 调试debug级
    # 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
    file_log_handler = rotatingfilehandler("logs/log", maxbytes=1024 * 1024 * 300, backupcount=10)
    # 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
    formatter = logging.formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
    # 为刚创建的日志记录器设置日志记录格式
    file_log_handler.setformatter(formatter)
    # 为全局的日志工具对象(flaskapp使用的)添加日志记录器
    logging.getlogger().addhandler(file_log_handler)

  在init_app方法中电泳上一步创建的方法,并传入config_name

   # 启用日志功能
    setup_log(config)

  在配置文件seetings/__init__.py中,设置日志等级

class config(object):
    """项目配置核心类"""
    # 调试模式
    debug = true

    # todo 配置日志
    log_level = "debug"

  八、创建蓝图

  application下的apps目录专门用于存放蓝图的。创建蓝图

  在apps下新建一个包,蓝图名为index,在包下面的__init.py文件中创建蓝图对象

from flask import blueprint

index_blu = blueprint("index_blu",__name__)

  在index蓝图目录下创建对应的视图文件,views.py

from . import index_blu

@index_blu.route("/")
def index():
    return "首页"

  在蓝图下的__init__.py文件中引入视图中的所有视图

from flask import blueprint

index_blu = blueprint("index_blu",__name__)

from .views import *

  在项目初始化文件application/__init__.py文件中注册蓝图对象

    # todo 注册蓝图对象到app应用中
    # 首页模块
    from .apps.index import index_blu
    app.register_blueprint(index_blu,url_prefix='')

  创建模型文件models.py

# coding=utf-8
from application import db

# 创建关系表,不再创建模型,一般用于表与表之间的多对多场景
"""
表关系变量 = db.table(
    "关系表表名",
    db.column('字段名', 字段类型, 字段选项),  # 普通字段
    db.column("字段名", 字段类型, db.foreignkey("表名.id")),
    db.column("字段名", 字段类型, db.foreignkey("表名.id")),
)
"""
achievement = db.table(
    "achievement",
    db.column('score', db.numeric, comment="分数"),
    db.column('student_id', db.integer, db.foreignkey('student.id')),
    db.column('course_id', db.integer, db.foreignkey('course.id'))
)

class student(db.model):
    """学生信息"""
    __tablename__ = "student"
    id = db.column(db.integer, primary_key=true, comment="主键id")
    name = db.column(db.string(64), index=true, comment="姓名" )
    sex = db.column(db.boolean, default=true, comment="性别")
    class_number = db.column(db.string(32), nullable=true, index=true, comment="班级")
    age = db.column(db.smallinteger, comment="年龄")
    description = db.column(db.text, comment="个性签名")
    courses = db.relationship(
        'course', # 模型名称
        secondary=achievement, # 表关系变量
        backref='students', # 当外键反过来获取主键信息时,使用的字段名称,可以自定义,接下来的使用例如: course.students 获取某个课程下所有的学生
        lazy='dynamic'
    )

    def __repr__(self):
        return "%s" % self.name

class course(db.model):
    """课程信息"""
    __tablename__ = "course"
    id = db.column(db.integer, primary_key=true,comment="主键id")
    name = db.column(db.string(64), unique=true,comment="课程名称")
    def __repr__(self):
        return "%s" % self.name

  数据库迁移:

python manage.py db init

python manage.py db migrate -m 'initial migration'

python manage.py db upgrade 

  完成学生表的增删改查

  views.py

from . import index_blu
from .models import student
from flask import render_template,request
from application import db
from flask import flash

@index_blu.route("/")
def index():
    """學生列表"""
    student_list = student.query.all()
    data = []
    for student in student_list:
        print(student.sex)
        data.append({
            "id":student.id,
            "name":student.name,
            "age":student.age,
            "sex":"男" if student.sex else "女",
            "description":student.description,
            "class_number":student.class_number,
        })

    return render_template("index.html",students=data)

@index_blu.route("/add",methods=["post","get"])
def add_student():
    if request.method == "post":
        # 接受數據
        name = request.form.get("username")
        age = int( request.form.get("age") )
        sex = true if request.form.get("sex") == '1' else false
        class_number = request.form.get("class_number")
        description = request.form.get("description")
        # 驗證數據
        if age < 0 or age > 120:
            # 閃現信息[用於返回錯誤信息給客戶端,只顯示一次]
            flash("非法的年齡數值")

        # 保存入庫
        student = student(name=name,age=age,sex=sex,class_number=class_number,description=description)
        try:
            db.session.add(student)
            db.session.commit()
        except:
            # 事務回滾
            db.session.rollback()

    return render_template("add.html")

  在蓝图下创一个templates目录,用于存放自己的模板

Flask入门之完整项目搭建

  在index/__init__.py文件中加入

#coding=utf-8
from flask import blueprint

index_blu = blueprint("index_blu",__name__,template_folder="templates")

from .views import *

  这个和django一样的,在查找模板时,先从全局的templates找,然后再去蓝图下面的templates中找

  九、闪现信息

  使用后,只会出现一次的信息,叫‘闪现信息’,用于在验证数据失败或者一些只需要显示一次性提示得场景。

  使用方法:

  在视图中当验证有误时,在显示模板之前设置flash

# 视图函数代码
from flask import flash

flash("对不起,您尚未登录,请登录!")

  模板中代码:

# 模板代码
{% for message in get_flashed_messages() %}
    <span>{{message}}</span>
{% endfor %}