flask综合案例
一.项目准备
1.新建项目目录students,并创建虚拟环境
mkvirtualenv students
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
3.在pycharm中打开项目目录编写manage.py启动项目的文件
(记得配置解释器为我们的虚拟环境解释器)
from flask import Flask app = Flask(__name__) @app.route('/index')
def index():
return 'index' if __name__ == '__main__':
app.run()
运行正常说明成功:
4.创建目录结构:
mange.py终不能存放大量的开发代码, 在开发中应该体现的是一种分工精神,所以我们可以把flask中各种功能代码进行分类分文件存储.
创建项目目录结构:
项目根目录/
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prop.py # 生产阶段的配置文件
│ ├── __init__.py # 项目初始化文件
├── manage.py # 项目的终端管理脚本文件
5.各配置文件的编写
配置文件
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
二.项目主应用中初始化项目
1.在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.py 中调用 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
项目初始化文件初始化mysql
# 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)
#
# 配置数据库链接
# 这个init_app是数据库那个类自身的函数,并不是当前的这个函数
db.init_app(app)
#
# # TODO 注册蓝图对象到app应用中
#
# return app
因为前面已经在settings中设置了数据库的配置信息,所以接下来,创建对应的数据库
create database students charset=utf8;
2.在manage启动文件中新增关于启动过程中的相关功能(数据库迁移等)
在项目根目录下`manage.py
中设置项目启动程序并调用__init__.py
的app
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()
三.日志的使用
Python 自身提供了一个用于记录日志的标准库模块:logging
FATAL/CRITICAL = 致命的,危险的
ERROR = 错误
WARNING = 警告
INFO = 信息
DEBUG = 调试
NOTSET = 没有设置
在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)
在application/__init__.py
项目初始化文件中,在init_app
方法中调用上一步创建的方法,并传入 config_name
# 启用日志功能
setup_log(Config)
在配置文件settings/__init__.py
中,设置默认日志等级
class Config(object):
"""项目配置核心类"""
# 调试模式
DEBUG = True # todo 配置日志
LOG_LEVEL = "DEBUG"
新增日志以后的项目目录结构(logs这个文件需要手动创建,否则会报错)
项目根目录/
├── docs/ # 项目开发相关文档
├── logs/ # 项目运行日志保存目录
| ├── log # 日志文件
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prop.py # 生产阶段的配置文件
│ ├── __init__.py # 项目初始化文件
├── manage.py # 项目的终端管理脚本文件
四.蓝图创建
在applications下创建apps目录,apps以后专门用于保存每一个项目的蓝图,
并在apps创建index蓝图目录,并在__init__.py
文件中创建蓝图对象
from flask import Blueprint index_blu = Blueprint("index_blu",__name__)
在index蓝图目录中新增对应的视图文件vies.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
文件中的init_app函数,注册蓝图对象
# TODO 注册蓝图对象到app应用中
# 首页模块
from .apps.index import index_blu
app.register_blueprint(index_blu,url_prefix='')
声明了蓝图目录以后的项目目录结构
项目根目录/
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prop.py # 生产阶段的配置文件
│ ├── __init__.py # 项目初始化文件
│ ├── statics/ # 保存项目中所有的静态资源文件[img/css/js]
│ ├── modules/ # 保存项目中所有蓝图的存储目录
│ │ ├── index # 蓝图目录
│ │ │ ├── __init__.py # 蓝图的初始化问年间
│ │ │ └── views.py # 蓝图的视图函数文件
│ │ ├── __init__.py
├── manage.py # 项目的终端管理脚本文件
index的模型代码: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'
) 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="课程名称")
在主应用中带入模型并迁移数据库
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#author tom
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) # 导入模型[为了进行数据迁移]
from application.apps.index import models @app.route('/')
def index():
return 'index' if __name__ == '__main__':
manager.run()
迁移数据库:
#因为上面已经把数据库迁移梦里添加了:
#所以直接 #初始化
python manage.py init #迁移
python manage.py migrate #生成报表
python manage.py upgrade
添加测试数据
insert into student values
(1,"赵华",1,307,22,"对于勤奋的人来说,成功不是偶然;对于懒惰的人来说,失败却是必然。"),
(2,"程星云",1,301,20,"人生应该如蜡烛一样,从顶燃到底,一直都是光明的。"),
(3,"陈峰",1,504,21,"在不疯狂,我们就老了,没有记忆怎么祭奠呢?"),
(4,"苏礼就",1,502,20,"不要为旧的悲伤,浪费新的眼泪。"),
(5,"张小玉",0,306,18,"没有血和汗水就没有成功的泪水。"),
(6,"吴杰",1,307,19,"以大多数人的努力程度之低,根本轮不到去拼天赋"),
(7,"张小辰",0,405,19,"人生的道路有成千上万条, 每一条路上都有它独自的风景。")
查看数据:在index.view编写视图
from flask import render_template, request, flash from application import db
from . import index_blu
from .models import Student @index_blu.route('/')
def index():
'''学生列表'''
student_list=Student.query.all()
data=[]
for student in student_list:
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.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="{{ url_for('index_blu.add') }}">新增学员</a>
<table border="1" width="1000" align="center">
<tr>
<th>id</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>班级</th>
<th>个性签名</th>
</tr>
{% for student in students %}
<tr>
<td>{{ student.id }}</td>
<td>{{ student.name }}</td>
<td>{{ student.age }}</td>
<td>{{ student.sex }}</td>
<td>{{ student.class_number }}</td>
<td>{{ student.description }}</td>
</tr>
{% endfor %} </table> </body>
</html>
添加数据:在index.view编写视图
@index_blu.route('/add',methods=['GET','POST'])
def add():
if request.method=='POST':
#接收数据
name=request.form.get('username')
age = int(request.form.get("age"))
sex = True if request.form.get("sex") == '' 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,sex=sex,class_number=class_number,description=description)
try:
db.session.add(student)
db.session.commit()
except Exception as e:
db.session.rollback() return render_template('add.html')
add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for message in get_flashed_messages() %}
<span>{{ message }}</span>
{% endfor %}
<form action="" method="post">
<table border="1" witdth="600" align="center">
<tr>
<td>姓名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>年龄:</td>
<td><input type="text" name="age"></td>
</tr>
<tr>
<td>性别:</td>
<td>
<select name="sex">
<option value="1">男</option>
<option value="0">女</option>
</select>
</td>
</tr>
<tr>
<td>班级:</td>
<td><input type="class_number"></td>
</tr>
<tr>
<td>個性簽名:</td>
<td><textarea name="description"></textarea></td>
</tr>
<tr>
<td> </td>
<td>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="submit" value="注册">
</td>
</tr> </table>
</form>
</body>
</html>
项目目录结构图:
五。闪现信息[flash]
使用后,只会出现一次的信息,叫“闪现信息”,用于在验证代码失败,或者一些只需要显示一次性提示的场景。
使用步骤:
视图中验证有误,则在显示模板之前设置flash
flash信息是通过session保存,也是从session中获取的,所以要设置app.config["SECRE_KEY"]
# 视图函数代码
from flask import flash flash("对不起,您尚未登录,请登录!")
模板代码:
# 模板代码
{% for message in get_flashed_messages() %}
<span>{{message}}</span>
{% endfor %}
flask综合案例的更多相关文章
- JavaScript:综合案例-表单验证
综合案例:表单验证 开发要求: 要求定义一个雇员信息的增加页面,例如页面名称为"emp_add.htmnl",而后在此页面中要提供有输入表单,此表单定义要求如下: .雇员编号:必须 ...
- DOM综合案例、SAX解析、StAX解析、DOM4J解析
今日大纲 1.DOM技术对xml的增删操作 2.使用DOM技术完成联系人管理 3.SAX和StAX解析 4.DOM4J解析 5.XPATH介绍 1.DOM的增删操作 1.1.DOM的增加操作 /* * ...
- JavaEE Tutorials (30) - Duke综合案例研究示例
30.1Duke综合应用的设计和架构456 30.1.1events工程458 30.1.2entities工程459 30.1.3dukes—payment工程461 30.1.4dukes—res ...
- jquery-easyUI第二篇【综合案例】
基于easyUI开发的一个综合案例模版 <%@ page language="java" pageEncoding="UTF-8"%> <!D ...
- CSS3_综合案例
综合案例 设置元素的 width,还可以利用 left 和 right 为了防止图片太小,background-size: 100% 100%; <!DOCTYPE html> <h ...
- Angular路由与多视图综合案例
Ajax请求存在的几个问题 (1)Ajax请求不会留下History 记录,会导致浏览器后退按钮失效 (2)用户无法直接通过URL进入应用中的指定页面(保存书签.链接分享给朋友) (3)Ajax对SE ...
- Winform开发框架中的综合案例Demo
在实际的系统开发中,我们往往需要一些简单的的案例代码,基于此目的我把Winform开发框架中各种闪光点和不错的功能,有些是我们对功能模块的简单封装,而有些则是引入了一些应用广泛的开源组件进行集成使用, ...
- 【原创 Hadoop&Spark 动手实践 13】Spark综合案例:简易电影推荐系统
[原创 Hadoop&Spark 动手实践 13]Spark综合案例:简易电影推荐系统
- Ext.js入门:常用组件与综合案例(七)
一:datefield简单示例 二:timefield简单示例 三:numberfield简单示例 四:FormPanel提交 datefield简单示例: <html xmlns=&quo ...
随机推荐
- Redis主从服务部署
Redis__WindowsServer主从服务部署及调用实例 一.先谈谈单个Redis服务的安装 使用的redis是2.8.17版本,从官网下载解压缩后文件内容为: ...
- 去除两张img中间的间隙
这样写 图片之间肯定有间隙 正确写法就是去掉空格 <img src="hlppic.png" /><img src="hlppic.png" ...
- HTML & CSS设计与构建网站 ([美]达科特) PDF原版
HTML & CSS 设计与构建网站采用有别于许多传统编程书籍的新颖编排方式,将使您收到事半功倍的学习效果.每一页都在短小精悍的示例代码的引导下,简明直观.直截了当地阐述一个新主题. < ...
- ICallbackEventHandler使用
后端:页面需继承ICallbackEventHandler protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack ...
- spring深入了解心得
spring 主要核心组件 :Core.上下文(Context) .实体(Bean): spring 主要由两大特色:控制反转(IOC).面向对象(AOP): spring中Core主要用于组建Bea ...
- Autofac的Autofac.Core.Activators.Reflection.DefaultConstructorFinder错误解决方案。
在使用Autofac的时候,不给力,看着例子来的,人家没问题,我就报了Autofac.Core.Activators.Reflection.DefaultConstructorFinder错误. 百般 ...
- UIButton的几种触发方式
1.说明 说明:由于是在"iOS 模拟器"中测试的,所以不能用手指,只能用鼠标. 1)UIControlEventTouchDown 指鼠标左键按下(注:只是"按下&qu ...
- MarkdownPad基于语法示例
博客园 [有道] (https://www.zybuluo.com/mdeditor#) [Markdown语法教学链接] (https://www.cnblogs.com/chimoxuanzhi/ ...
- 20165219第4次实验《Android程序设计》实验报告
20165219第4次实验<Android程序设计>实验报告 一.实验内容及步骤 (一)Android Stuidio的安装Hello world测试 要求 参考http://www.cn ...
- javascript立即执行函数与模块化
概念:立即执行函数顾名思义就是函数定义好之后立即执行.函数表达式方式:函数表达式后面加括号()即可立即执行函数. var xmlhttpUtil = function () { function ge ...