flask——demo
综合案例:学生成绩管理
新建项目目录stud, 并创建虚拟环境stud
mkvirtualenv stud -p python3
安装开发中使用的依赖模块
pip install flask==0.12.4 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install redis==3.2.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-session==0.3.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-script==2.0.6 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-mysqldb==0.2.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask-migrate==2.5.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install flask_wtf==0.14.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install Faker==2.0.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
在pycharm中打开项目目录,设置虚拟环境以后,编写manage.py启动项目的文件
mkdir ~/Desktop/stud
创建 manage.py 文件
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
if __name__ == '__main__':
app.run()
mange.py终不能存放大量的开发代码, 在开发中应该体现的是一种分工精神,所以我们可以把flask中各种功能代码进行分类分文件存储.
创建项目目录结构:
项目根目录/
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prop.py # 生产阶段的配置文件
│ ├── __init__.py # 项目全局初始化文件[全局配置]
├── manage.py # 项目的终端管理脚本文件
配置文件
settings/__init__.py代码:
from redis import Redis
class Config():
"""配置类"""
"""调试模式"""
DEBUG = True
"""密钥"""
# 密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串
SECRET_KEY = "ghhBljAa0uzw2afLqJOXrukORE4BlkTY/1vaMuDh6opQ3uwGYtsDUyxcH62Aw3ju"
"""日志管理"""
"""数据库"""
# mysql数据库的配置信息
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= False
"""redis"""
REDIS_HOST = '127.0.0.1' # 项目上线以后,这个地址就会被替换成真实IP地址,mysql也是
REDIS_PORT = 6379
"""session"""
SESSION_TYPE = "redis" # 指定 session 保存到 redis 中
SESSION_USE_SIGNER = True # 让 cookie 中的 session_id 被加密签名处理
SESSION_REDIS = Redis(host=REDIS_HOST, port=REDIS_PORT,db=1) # 使用 redis 的实例
PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session_id的有效期,单位是秒
settings/dev.py代码:
from . import Config
class DevConfig(Config):
"""开发模式下的配置"""
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= True
SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/student?charset=utf8"
settings/prod.py代码:
from . import Config
class ProdConfig(Config):
"""生产模式下的配置"""
DEBUG = False
SQLALCHEMY_ECHO = False
项目主应用中初始化项目
在application/__init__.py文件中,创建flask应用并加载配置
from flask import Flask
from application.settings.dev import Devonfig
from application.settings.prod import ProdConfig
def init_app(config_name):
"""项目初始化函数"""
app = Flask(__name__)
# 加载配置
config = {
"dev": DevConfig,
"prod": ProdConfig
}
app.config.from_object(config.get(model))
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 Devonfig
from application.settings.prod import ProdConfig
config_dict = {
"dev": DevConfig,
"prod": ProdConfig,
}
# 为了方便redis的连接对象在函数外部可以使用,预先设置一个全局变量,接下来在函数中用于保存redis的连接
redis_store = None
def init_app(config_name):
"""项目的初始化功能"""
app = Flask(__name__)
# 设置配置类
Config = config.get(config_name)
# 加载配置
app.config.from_object(Config)
# redis的链接初始化
app.redis = Redis(host=Config.REDIS_HOST, port=Config.REDIS_PORT,db=0)
# 开启CSRF防范功能
CSRFProtect(app)
# 开启session功能
Session(app)
# TODO 注册蓝图对象到app应用中
return app
调整redis的加载,把redis的配置信息和初始化代码进行分离
新建文件application/utils/helper.py,helper.py后面用于保存一些自己封装的工具助手函数.代码:
from redis import Redis
def get_redis_connection(**option):
return Redis(host=option.get("host"), port=option.get("port"), db=option.get("db"))
application/settings/__init__.py,代码:
from redis import Redis
from application.utils.helper import get_redis_connection
import os
class Config(object):
"""调试模式"""
DEBUG = True
"""密钥"""
# 密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串
SECRET_KEY = "ghhBljAa0uzw2afLqJOXrukORE4BlkTY/1vaMuDh6opQ3uwGYtsDUyxcH62Aw3ju"
"""日志管理"""
"""数据库"""
# mysql数据库的配置信息
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO = False
"""redis配置"""
REDIS = {
'default':{
'host':'127.0.0.1', # 项目上线以后,这个地址就会被替换成真实IP地址,mysql也是
'port':6379,
'db': 0
},
'session':{
'host': '127.0.0.1', # 项目上线以后,这个地址就会被替换成真实IP地址,mysql也是
'port': 6379,
'db': 1
}
}
"""session"""
SESSION_TYPE = "redis" # 指定 session 保存到 redis 中
SESSION_USE_SIGNER = True # 让 cookie 中的 session_id 被加密签名处理
SESSION_REDIS = get_redis_connection(**REDIS["session"]) # 使用 redis 的实例
PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session_id的有效期,单位是秒
在主应用application的初始化__init__py_中使用redis可以如下使用:
mange.py代码:
from flask import Flask
from application.settings.dev import DevConfig
from application.settings.prod import ProdConfig
from flask_wtf import CSRFProtect
from flask_session import Session
from application.utils.flask_redis import get_redis_connection
def init_app(config_name):
"""项目初始化函数"""
config_dict = {
"dev": DevConfig,
"prod": ProdConfig,
}
Config = config_dict.get(config_name)
# 初始化框架
app = Flask(__name__)
app.config.from_object(Config)
# 初始化数据库
# 初始化redis
app.redis = get_redis_connection(Config.REDIS["default"])
# 初始化CSRF
CSRFProtect(app)
# 初始化session
Session()
return app
manage.py,代码:
from application import init_app
app = init_app("dev")
@app.route('/')
def index():
app.redis.set("mobile","123456")
return 'index'
if __name__ == '__main__':
app.run()
增加数据库配置
from flask import Flask
from application.settings.dev import DevConfig
from application.settings.prod import ProdConfig
from flask_wtf import CSRFProtect
from flask_session import Session
from application.utils.flask_redis import get_redis_connection
from flask_sqlalchemy import SQLAlchemy
def init_app(config_name):
"""项目初始化函数"""
config_dict = {
"dev": DevConfig,
"prod": ProdConfig,
}
Config = config_dict.get(config_name)
# 初始化框架
app = Flask(__name__)
app.config.from_object(Config)
# 初始化数据库
app.db = SQLAlchemy(app)
# 初始化redis
app.redis = get_redis_connection(Config.REDIS["default"])
# 初始化CSRF
CSRFProtect(app)
# 初始化session
Session()
return app
因为前面已经在settings中设置了数据库的配置信息,所以接下来,创建对应的数据库
create database student charset=utf8mb4;

在manage启动文件中新增关于启动过程中的相关功能
在项目根目录下``manage.py中设置项目启动程序并调用init.py`的app
from flask import Flask
from application.settings.dev import DevConfig
from application.settings.prod import ProdConfig
from flask_wtf import CSRFProtect
from flask_session import Session
from application.utils.flask_redis import get_redis_connection
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
db = SQLAlchemy()
def init_app(config_name):
"""项目初始化函数"""
config_dict = {
"dev": DevConfig,
"prod": ProdConfig,
}
Config = config_dict.get(config_name)
# 初始化框架
app = Flask(__name__)
app.config.from_object(Config)
# 初始化数据库
db.init_app(app)
# 初始化redis
app.redis = get_redis_connection(Config.REDIS["default"])
# 初始化CSRF
CSRFProtect(app)
# 初始化session
Session()
# 初始化终端脚本
app.manage = Manager(app)
# 初始化数据迁移
Migrate(app,db)
app.manage.add_command("db",MigrateCommand)
return app
在mange.py中启动项目
from application import init_app
app = init_app("dev")
@app.route('/')
def index():
app.redis.set("mobile","123456")
return 'index'
if __name__ == '__main__':
app.manage.run()
日志
Python 自身提供了一个用于记录日志的标准库模块:logging。
日志的等级
FATAL/CRITICAL = 致命的,危险的
ERROR = 错误
WARNING = 警告
INFO = 信息
DEBUG = 调试
NOTSET = 没有设置
把日志设置封装成一个函数,写在utils目录下
import logging
from logging.handlers import RotatingFileHandler
def setup_log(Config):
# 设置日志的记录等级
logging.basicConfig(level=Config.LOG_LEVEL) # 调试debug级
# 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
file_log_handler = RotatingFileHandler(
Config.LOG_FILE_PATH,
maxBytes=Config.LOG_FILE_SIZE, backupCount=Config.LOG_FILE_NUMBER)
# 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
formatter = logging.Formatter('%(levelname)s %(asctime)s %(filename)s:%(lineno)d %(message)s')
# 为刚创建的日志记录器设置日志记录格式
file_log_handler.setFormatter(formatter)
# 为全局的日志工具对象(flaskapp使用的)添加日志记录器
logging.getLogger().addHandler(file_log_handler)
在 init_app 方法中调用上一步创建的方法,并传入 config_name
application/__init__.py,代码:
import logging
from flask import Flask
from application.settings.dev import DevConfig
from application.settings.prod import ProdConfig
from flask_wtf.csrf import CSRFProtect
from flask_session import Session
from application.utils.helper import get_redis_connection
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager,Command
from flask_migrate import Migrate,MigrateCommand
from application.utils.log import setup_log
config_dict = {
"dev": DevConfig,
"prod": ProdConfig,
}
db = SQLAlchemy()
def init_app(config_name):
"""项目初始化函数"""
# 创建app应用
app = Flask(__name__)
# 根据选项获取配置类
Config = config_dict.get(config_name)
# 加载配置
app.config.from_object(Config)
# 日志初始化
setup_log(Config)
app.log = logging.getLogger()
# redis数据库
app.redis = get_redis_connection(Config.REDIS["default"])
# 初始化数据库
db.init_app(app)
# 开启CSRF防范功能
CSRFProtect(app)
# 开启session功能
Session(app)
# 初始化终端脚本
app.manage = Manager(app)
# 初始化数据迁移
Migrate(app,db)
app.manage.add_command("db",MigrateCommand)
# TODO 注册蓝图对象到app应用中
return app
在配置文件settings/__init__.py中,设置默认日志等级并设置当前项目主应用目录作为一个配置常量
from redis import Redis
from application.utils.flask_redis import get_redis_connection
class Config():
"""配置类"""
# 当前项目主应用目录
BASE_DIR = os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) )
"""调试模式"""
DEBUG = True
"""密钥"""
# 密钥,可以通过 base64.b64encode(os.urandom(48)) 来生成一个指定长度的随机字符串
SECRET_KEY = "ghhBljAa0uzw2afLqJOXrukORE4BlkTY/1vaMuDh6opQ3uwGYtsDUyxcH62Aw3ju"
"""日志管理"""
LOG_LEVEL = "DEBUG"
LOG_FILE_PATH = "logs/log"
LOG_FILE_SIZE = 1024 * 1024 * 300
LOG_FILE_NUMBER = 10
"""数据库"""
# mysql数据库的配置信息
SQLALCHEMY_DATABASE_URI = ""
# 动态追踪修改设置,如未设置只会提示警告
SQLALCHEMY_TRACK_MODIFICATIONS = False
# 查询时会显示原始SQL语句
SQLALCHEMY_ECHO= False
"""redis配置"""
REDIS = {
'default':{
'host':'127.0.0.1', # 项目上线以后,这个地址就会被替换成真实IP地址,mysql也是
'port':6379,
'db': 0
},
'session':{
'host': '127.0.0.1', # 项目上线以后,这个地址就会被替换成真实IP地址,mysql也是
'port': 6379,
'db': 1
}
}
"""session"""
SESSION_TYPE = "redis" # 指定 session 保存到 redis 中
SESSION_USE_SIGNER = True # 让 cookie 中的 session_id 被加密签名处理
SESSION_REDIS = get_redis_connection(**REDIS["session"]) # 使用 redis 的实例
PERMANENT_SESSION_LIFETIME = 24 * 60 * 60 # session_id的有效期,单位是秒
项目的生产环境配置文件中,设置默认的日志等级为“INFO”或者“WARNING”
如果要在manage.py测试日志功能,可以使用以下代码:
from application import init_app
app = init_app("prod")
@app.route('/')
def index():
try:
1 / 0
except:
app.log.error("程序出错!")
app.redis.set("mobile","123456")
return 'index'
if __name__ == '__main__':
app.manage.run()
新增日志以后的项目目录结构
项目根目录/
├── docs/ # 项目开发相关文档
├── logs/ # 项目运行日志保存目录
| ├── student.log # 日志文件
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prop.py # 生产阶段的配置文件
│ ├── __init__.py # 项目初始化文件
├── manage.py # 项目的终端管理脚本文件
经过上面的改造,我们接下来就可以开始创建蓝图了。
创建蓝图目录
在applications下创建apps目录,apps以后专门用于保存每一个项目的蓝图,
并在apps创建home蓝图目录,并在__init__.py文件中创建蓝图对象
from flask import Blueprint
home_blu = Blueprint("home",__name__)
from .views import *
在home蓝图目录中新增对应的视图文件views.py,代码:
from . import home_blu
@home_blu.route("/")
def index():
return "hemo"
在application/__init__.py的init_app函数中,引入home_blu蓝图下视图文件
import logging
import sys
import os
def init_app(config):
"""项目初始化函数"""
# ....
# 配置视图的存储目录为默认导包路径
sys.path.insert(0, Config.BASE_DIR)
sys.path.insert(0, os.path.join(Config.BASE_DIR, "apps"))
# 蓝图注册
from home import home_blu
app.register_blueprint(home_blu, prefix="")
return app
声明了蓝图目录以后的项目目录结构
项目根目录/
├── application/ # 项目主要逻辑代码保存目录
| ├── settings/ # 项目配置存储目录
│ │ ├ dev.py # 开发阶段的配置文件
│ │ ├ prop.py # 生产阶段的配置文件
│ ├── __init__.py # 项目初始化文件
│ ├── apps/ # 保存项目中所有蓝图的存储目录
│ │ ├── home/ # 蓝图目录
│ │ │ ├── __init__.py # 蓝图的初始化问年间
│ │ │ └── views.py # 蓝图的视图函数文件
│ │ ├── __init__.py
├── manage.py # 项目的终端管理脚本文件
模型创建
通行也可以通过不同的蓝图进行分开存放.我们把之前声明的课程\学生\成绩关系\老师的模型提取过来
from application import db
"""
# 创建关系表,不再创建模型,一般用于表与表之间的多对多场景
表关系变量 = db.Table(
"关系表表名",
db.Column('字段名', 字段类型, 字段选项), # 普通字段
db.Column("字段名", 字段类型, db.ForeignKey("表名.id")),
db.Column("字段名", 字段类型, db.ForeignKey("表名.id")),
)
"""
achievement = db.Table(
"tb_achievement",
db.Column('score', db.Numeric, comment="分数"),
db.Column('student_id', db.Integer, db.ForeignKey('tb_student.id')),
db.Column('course_id', db.Integer, db.ForeignKey('tb_course.id'))
)
"""
class Achievement(db.Model):
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
db.Column('score', db.Numeric, comment="分数"),
student_id = db.Column(db.Integer, db.ForeignKey('tb_student.id'))
course_id = db.Column(db.Integer, db.ForeignKey('tb_course.id'))
"""
class Student(db.Model):
"""学生信息"""
__tablename__ = "tb_student"
# comment 表示 字段的注释
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
# index 设置普通索引,目的: 加快查询数据的速度
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="个性签名")
# score = db.relationship('Achievement', backref='student', lazy='dynamic')
# 并非表字段,而是模型的属性
courses = db.relationship(
'Course', # 模型名称
secondary=achievement, # 表关系变量
backref='students', # 当外键反过来获取主键信息时,使用的字段名称,可以自定义,接下来的使用例如: course.students 获取某个课程下所有的学生
lazy='dynamic'
)
class Course(db.Model):
"""课程信息"""
__tablename__ = "tb_course"
id = db.Column(db.Integer, primary_key=True, comment="主键ID")
name = db.Column(db.String(64), unique=True, comment="课程名称")
# score = db.relationship('Achievement', backref='course', lazy='dynamic')
注册蓝图下面的模型到manage.py文件中
from application import app
# 注册模型
from home.models import *
if __name__ == '__main__':
app.manager.run()
模型的数据迁移
python manage.py db init # 项目刚创建时进行初始化
python manage.py db migrate -m '创建基本数据库'
python manage.py db upgrade
添加测试数据
在application/utils/command.py里面创建一个生成测试数据的自定义命令
from flask_script import Command
from home.models import Student
from faker import Faker
from application import db
import random
class CreateDataCommand(Command):
"""生成学生测试数据"""
def run(self):
faker = Faker(locale="zh_CN")
data = []
num = 0
for _ in range(100):
sex = random.randint(0, 1)
try:
student = Student(
name=faker.name_female() if sex else faker.name_male(),
sex=not not sex,
description=faker.sentence(nb_words=6, variable_nb_words=True, ext_word_list=None),
age=random.randint(13, 28)
)
db.session.add(student)
db.session.commit()
num+=1
except:
pass
print("本次共生成了%s个数据" % num)
在manage.py中注册命令
from application.utils.command import CreateDataCommand
app.manage.add_command("test",CreateDataCommand() )
在终端下,执行以下命令即可创建100个用户
python manage.py test
上面有了学生信息以后,我们可以在index蓝图下,创建基于前后端不分离模式的6个视图:
from . import home_blu
@home_blu.route("/",methods=["get"])
def index():
return "学生列表页面"
@home_blu.route("/add",methods=["get"])
def add():
return "添加学生信息页面"
@home_blu.route("/create",methods=["post"])
def create():
return "添加学生功能"
@home_blu.route("/edit",methods=["get"])
def edit():
return "编辑学生信息页面"
@home_blu.route("/update",methods=["put"])
def update():
return "更新学生信息功能"
@home_blu.route("/delete",methods=["delete"])
def delete():
return "删除学生信息功能"
在蓝图中设置当前蓝图的模板和静态目录,在application/apps/home目录下创建templates和static目录,
并修改home蓝图下的__init__.py,代码:
from flask import Blueprint
home_blu = Blueprint("home",__name__, static_folder="static", static_url_path="/statics", template_folder="templates")
from .views import *
完成学生信息列表页面
application/apps/home/views.py,视图代码:
from . import index_blu
from flask import render_template
from .models import Student
@index_blu.route("/",methods=["get"])
def index():
# 查询学生信息
student_list = Student.query.all()
return render_template("list.html",**{
"student_list":student_list,
})
@index_blu.route("/add",methods=["get"])
def add():
return "添加学生信息页面"
@index_blu.route("/create",methods=["post"])
def create():
return "添加学生功能"
@index_blu.route("/edit",methods=["get"])
def edit():
return "编辑学生信息页面"
@index_blu.route("/update",methods=["put"])
def update():
return "更新学生信息功能"
@index_blu.route("/delete",methods=["delete"])
def delete():
return "删除学生信息功能"
模板代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/statics/list.css">
</head>
<body>
<h1>学生成绩信息录入系统</h1>
<table>
<tr>
<td><a href="/add">添加信息</a></td>
</tr>
<tr>
<th>ID</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>操作</th>
</tr>
{% for student in student_list %}
<tr>
<td>{{ student.id }}</td>
<td>{{ student.name }}</td>
<td>{{ student.age }}</td>
<td>{{ "男" if student.sex else "女" }}</td>
<td>
<a href="/edit/{{ student.id }}">编辑</a>
<a href="/delete/{{ student.id }}">删除</a>
</td>
</tr>
{% endfor %}
</table>
</body>
</html>
在home/static/list.css,代码:
body{
background-color: #eee;
color: #333;
}
h1{
font-weight: normal;
text-align: center;
}
table{
border-collapse: collapse;
border: 1px solid red;
margin: 30px auto;
}
tr{
height: 32px;
line-height: 32px;
}
td,th{
font-weight: normal;
text-align: center;
padding: 4px 7px;
font-size: 14px;
border: 1px solid red;
width: 120px;
}
添加学生信息
home/add.html,基本模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body{
background-color: #eee;
color: #333;
}
h1{
font-weight: normal;
text-align: center;
}
table{
border-collapse: collapse;
border: 1px solid red;
margin: 30px auto;
}
tr{
height: 32px;
line-height: 32px;
}
td,th{
font-weight: normal;
text-align: center;
padding: 4px 7px;
font-size: 14px;
border: 1px solid red;
width: 120px;
}
input[type=text],
textarea{
width: 100%;
background-color: transparent;
border: none;
height: 32px;
outline: none;
}
input[type=submit]{
width: 120px;
height: 32px;
font-size: 17px;
color: #333;
text-align: center;
background: none;
border: none;
outline: none;
cursor: pointer;
}
</style>
</head>
<body>
<h1>学生成绩信息录入系统</h1>
<form action="/create" method="post">
<table>
<tr>
<td>姓名</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>年龄</td>
<td><input type="text" name="age"></td>
</tr>
<tr>
<td>性别</td>
<td>
<label><input type="radio" name="sex" value="0"> 女</label>
<label><input type="radio" name="sex" value="1"> 男</label>
</td>
</tr>
<tr>
<td>个性签名</td>
<td>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<textarea name="description"></textarea>
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
添加数据提交后端
from . import home_blu
from .models import Student
from flask import render_template,request, redirect,url_for
from application import db
@home_blu.route("/",methods=["get"])
def index():
student_list = Student.query.all()
return render_template("list.html", **{
"student_list": student_list,
})
@home_blu.route("/add",methods=["get"])
def add():
return render_template("add.html")
@home_blu.route("/create",methods=["post"])
def create():
# 接受数据
try:
name = str( request.form.get("name") )
age = int( request.form.get("age") )
sex = bool( int( request.form.get("sex") ) )
except:
return redirect(url_for("home.add"))
# 校验数据
res = Student.query.filter(Student.name==name).first()
if res:
# 返回添加数据的表单视图中
return redirect( url_for("home.add") )
# 添加数据
try:
student = Student(name=name, age=age, sex=sex)
db.session.add(student)
db.session.commit()
# 返回列表数据视图中
return redirect( url_for("home.index") )
except:
# 返回添加数据的表单视图中
return redirect(url_for("home.add"))
@home_blu.route("/edit",methods=["get"])
def edit():
return "编辑学生信息页面"
@home_blu.route("/update",methods=["put"])
def update():
return "更新学生信息功能"
@home_blu.route("/delete",methods=["delete"])
def delete():
return "删除学生信息功能"
闪现信息[flash]
使用后,只会出现一次的信息,叫“闪现信息”,用于在验证代码失败,或者一些只需要显示一次性提示的场景。
使用步骤:
视图中验证有误,则在显示模板之前设置flash
# 视图函数代码
from flask import flash
flash("对不起,您尚未登录,请登录!")
模板代码:
# 模板代码
{% for message in get_flashed_messages() %}
<span>{{message}}</span>
{% endfor %}
使用闪现信息显示错误提示
视图:
from . import home_blu
from .models import Student
from flask import render_template,request, redirect,url_for,flash
from application import db
@home_blu.route("/",methods=["get"])
def index():
student_list = Student.query.all()
return render_template("list.html", **{
"student_list": student_list,
})
@home_blu.route("/add",methods=["get"])
def add():
return render_template("add.html")
@home_blu.route("/create",methods=["post"])
def create():
# 接受数据
try:
name = str( request.form.get("name") )
age = int( request.form.get("age") )
sex = bool( int( request.form.get("sex") ) )
except:
flash("对不起,数据格式有误!")
return redirect(url_for("home.add"))
# 校验数据
res = Student.query.filter(Student.name==name).first()
if res:
# 返回添加数据的表单视图中
flash("对不起,当前用户已经注册!")
return redirect( url_for("home.add") )
# 添加数据
try:
student = Student(name=name, age=age, sex=sex)
db.session.add(student)
db.session.commit()
# 返回列表数据视图中
return redirect( url_for("home.index") )
except:
flash("对不起,添加用户失败!")
# 返回添加数据的表单视图中
return redirect(url_for("home.add"))
@home_blu.route("/edit",methods=["get"])
def edit():
return "编辑学生信息页面"
@home_blu.route("/update",methods=["put"])
def update():
return "更新学生信息功能"
@home_blu.route("/delete",methods=["delete"])
def delete():
return "删除学生信息功能"
add.html,模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body{
background-color: #eee;
color: #333;
}
h1{
font-weight: normal;
text-align: center;
}
table{
border-collapse: collapse;
border: 1px solid red;
margin: 30px auto;
}
tr{
height: 32px;
line-height: 32px;
}
td,th{
font-weight: normal;
text-align: center;
padding: 4px 7px;
font-size: 14px;
border: 1px solid red;
width: 120px;
}
input[type=text],
textarea{
width: 100%;
background-color: transparent;
border: none;
height: 32px;
outline: none;
}
input[type=submit]{
width: 120px;
height: 32px;
font-size: 17px;
color: #333;
text-align: center;
background: none;
border: none;
outline: none;
cursor: pointer;
}
</style>
</head>
<body>
<h1>学生成绩信息录入系统</h1>
<form action="/create" method="post">
<table>
<tr>
<td>姓名</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>年龄</td>
<td><input type="text" name="age"></td>
</tr>
<tr>
<td>性别</td>
<td>
<label><input type="radio" name="sex" value="0"> 女</label>
<label><input type="radio" name="sex" value="1"> 男</label>
</td>
</tr>
<tr>
<td>个性签名</td>
<td>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<textarea name="description"></textarea>
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"></td>
</tr>
</table>
</form>
<script>
{% for message in get_flashed_messages() %}
alert("{{ message }}");
{% endfor %}
</script>
</body>
</html>

浙公网安备 33010602011771号