Flask
2017-03-14 15:55:56 0 举报
AI智能生成
Flask是一个用Python编写的轻量级Web应用框架。它的核心是一个简单的WSGI(Web Server Gateway Interface)应用,可以方便地与其他Python库或框架集成。Flask的设计目标是使开发者能够快速构建Web应用,同时保持代码简洁和可读性。 Flask具有灵活的路由系统,可以轻松地定义URL规则和处理函数。它还支持模板引擎,如Jinja2,使得在HTML中嵌入Python代码变得简单。此外,Flask还提供了许多内置的扩展,如用户认证、文件上传等,以满足各种需求。 总之,Flask是一个易于上手且功能强大的Web开发框架,适用于各种规模的项目。
作者其他创作
大纲/内容
学习网站
http://www.pythondoc.com/
简介http://flask.pocoo.org/
轻量级
基于Werkzeug WSGI
微框架核心简单
特色
子主题
集成单元测试
Jinja2
RESTFaul
Unicode
丰富的扩展
安装与配置
创建虚拟隔离环境
最新版本python
进入目标目录 C:\site
创建 python -m venv myenv
激活
Windows myenv\Scripts\activate
Linux source myenv\bin\activate
退出
deactivate
pip安装组建
激活虚拟环境上下文
pip install flask
快速实例
站点结构
site
static
images
js
css
入口类
Flask()实例
@app.route('/') 路由装饰器响应处理函数
程序配置 app.debug=True
程序运行
templates
index.html
......
请求/响应流程
路由接受请求
分配请求给特定视图函数
视图函数返回视图
核心对象
请求 request
上下文
浏览器自动创建
手动创建:context=app.test_request_context('/path/',methon='post'
context.push()
request.path
context.pop()
地址编码
编码
urlib.parse.quote('params')
{{ params|urlencode }}
解码
urlib.parse.unquote('params')
成员属性
.path 请求路径
.method 方法
.args.get('key','None') 地址栏查询字符串
form 表单成员
request.form['name']
request.form.get('pwd')
request.values['name'] 查询字符串/表单数据
request.headers 头部信息
request.headers['User-Agen'] 浏览器
request.headers['Host'] 主机
。。。。。
响应 response
构造
构造 make.response(响应内容,状态码,头部信息)
.response 响应内容
.status_code = 200 / .status = '200'
.headers['conten-type'] = 'text/html' (头部信息字典表)
重定向请求 redirect(url,code=301|302)
根据终节点生产匹配的url: url_for(endpoint函数)
抛出状态码 abort()
呈现特定目录资源 send_from_directory
模板 Jinja2
基本语法
{{ 变量 }}
{% 语句 %}
{# 注释 #}
模板继承
布局页
{% block 内容占位符 %}...{% endblock %}
内容页
{% extends 'base.html' %}
{% block 内容占位符 %}自定义内容{% endblock %}
循环相关属性
loop.index 索引
loop.index0
视图函数传参
函数 def xxx(prm)
{{ url_for('xxx',prm=item.id) }}
Flask Message
flask:flash('message')
html: {% get_flasked_messages() %}
sqlite3
导入 import sqlite3
连接数据库 conn = salite.connect(r'.\db\...')
游标 c = conn.cursor()
sql 语句
查询 sql = "select。。。 from 。。。"
排序 order by ....desc (倒序)
插入 sql = "insert into 表名(.naem,id,...) values(?,?,....)"
修改
修改 update 表名 set 列名= 新值 where id in (103,104, 476)
修改 update 表名 set 列名= substr(列名,0,19) 只留下列的前19个字段
执行 feedbacks = c.execute(sql,('jz',3,...)
提交 conn.commit()
inster into
delete
关联数据表
sql = "select f.ROWID, f.*, c.CategoryName from feedback f inner jion category c ON c.ROWID == f.CategotyID
关闭数据库 conn.close()
从文件导入到数据库的软件 navicat
数据库管理
图片上传
<input type='file'>
<form enctype='multipart/form-data'>
定义图片格式 ALLOWED_EXTESIONS = ['.jpg', '.png', '.gif']
# 检查图片是否允许上传
def allowed_file(filename):
# fiename = 'aospppss.JPG/jpg'
_, ext = os.path.splitext(filename)
return ext.lower() in ALLOWED_EXTESIONS
def allowed_file(filename):
# fiename = 'aospppss.JPG/jpg'
_, ext = os.path.splitext(filename)
return ext.lower() in ALLOWED_EXTESIONS
判断是否有图片和给图片重命名及保存路径
img_path = None
if request.files.get('imagepath', None):
img = request.files['imagepath']
if allowed_file(img.filename):
img_path = datetime.now().strftime('%Y%m%d%H%M%f') + os.path.splitext(img.filename)[1]
img.save(os.path.join(UPLOAD_FOLDER, img_path))
img_path = None
if request.files.get('imagepath', None):
img = request.files['imagepath']
if allowed_file(img.filename):
img_path = datetime.now().strftime('%Y%m%d%H%M%f') + os.path.splitext(img.filename)[1]
img.save(os.path.join(UPLOAD_FOLDER, img_path))
状态管理
会话状态 Session
功能用途:在不同请求中共享信息
编码
给程序设置安全码 app.secret_key
声明:session['键'] = 值
获取
session['键']
session.get['键','默认值']
清除/退出:session.pop('键')
防止后退时找到历史记录,退出时连接到登录后的页面
Cookie
机制:服务器端发送的小段文本信息存储在客户端硬盘
功能
记录用户偏好
请求、页面、站点间共享信息
特点
易丢失
安全性
操作
写入
resp = make_response()
resp.set_cookie()
key
value
domain 作用域名
path 作用路径
时间
max_age 生命周期秒数
expires 过期时间
获取
request.cookies.get('key')
删除
重设过期时间再写入覆盖
可拔插视图
基于类的视图
写类 继承自 flask.views.View
实现方法 dispatch_request(self)
app 注册网址规则
导入视图类
app.add_url_rule('path', view_func=类名.as_view('终节点名')
基于方法的视图
类继承自 flask.views.MethodView
GET def get(self):
POST def post(self):
PUT def put(self):
Blueprint 实现程序模块化
创建Blueprint
from flask import Blueprint
bp = Blueprint('bp',__name__)
@bp.route('/')
注册
from xxx import bp
app.register_buleprint(bp,url_prefix='/bp')
生成链接
url_for('blueprint.view_func',key=value)
ORM
SQLAlchemy
安装flask-sqlaichemy
配置
导入 : from flask_sqlalchemy import SQLALchemy
创建数据库核心对象: db = SQLALchemy(app)
数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] ='连接字符串'
sqlite:///./path/to/database.db
基本形式:别名+驱动://用户名:密码@主机:端口/数据库
mysql://jz:123456@127.0.0.1:3306/mydatebase
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True (是否跟踪修改)
app.config['SQLALCHEMY_ECHO'] = True (是否打印SQL)
模型类
功能:对应生成数据库表
基类:db.Model
列: db.Column(类型、选项)
类型
db.Integer() 整型
db.String() 字符串
db.Text() 文本
db.DateTime() 日期时间
db.Float() 浮点
db.Boolean() 布尔
db.PickleType() pickle 序列对象
db.LargeBinary() 大二进制对象
选项
primary_key 是否主键
unique 是否唯一
default = 默认值
关系(一对多)
外键 db.Column(db.Integer, db.Foreignkey('表名.id')
db.relationship('主键类名', backref='引用属性名', lazy='dynamic')
dynamic 动态
select
subquery
joined
核心对象
db.create.all() 创建所有表
db.drop.all() 删除所有表
类的应用
构造类
from collections import namedtuple
Book = namedtuple('Book',['title','price','author']
实例: book1 = Book('python',39,'刘哲')
book1.naem =
应用
导入创建的类: Employee,Department 在F盘pms 的文件
row
for row in Employee.query.all: print (row.name, row.id)
label
for row in db.session.query(Employee.name.label('姓名')):
print(row.姓名)
print(row.姓名)
limit
for emp in Employee.query.limit(5):
print(emp) 打印前5个
print(emp) 打印前5个
for emp in db.session.query(Employee).order_by(Employee.salary).limit(5):
print(emp) 按工资升序的前5个
print(emp) 按工资升序的前5个
offset()
for emp in Employee.query.order_by(Employee.salary).offset(10).limit(10):
print(emp) 跳过10再取10个
print(emp) 跳过10再取10个
filter_by
for emp in db.session.query(Employee).filter_by(name='齐珍生'):
print(emp) 找姓名等于齐珍生的
print(emp) 找姓名等于齐珍生的
contains
for emp in db.session.query(Employee).filter(Employee.name.contains('小')):
print(emp) 姓名中包含 小 字的
print(emp) 姓名中包含 小 字的
filter
for emp in db.session.query(Employee).filter(Employee.name=='齐珍生'):
print(emp) 找姓名等于齐珍生的
print(emp) 找姓名等于齐珍生的
for emp in Employee.query.filter(Employee.salary > 7000.0):
print(emp) 工资大于7000
print(emp) 工资大于7000
startswith
for emp in Employee.query.filter(Employee.name.startswith('刘')):
print(emp) 找出姓刘的 (即以刘开头)
print(emp) 找出姓刘的 (即以刘开头)
for emp in Employee.query.filter(Employee.salary > 5000.0).filter(Employee.name.startswith('王')):
print(emp) 工资大于5000姓王的
print(emp) 工资大于5000姓王的
for emp in Employee.query.filter(Employee.salary > 5000.0).filter(Employee.gender=='男').filter(Employee.name.startswith('刘')):
print(emp) 大于5000姓刘的男人
print(emp) 大于5000姓刘的男人
like
for emp in Employee.query.filter(Employee.name.like('刘%')):
print(emp) 找出姓刘的
print(emp) 找出姓刘的
for emp in db.session.query(Employee).filter(Employee.name.like('%龙%')):
print(emp) 姓名中包含龙字的
print(emp) 姓名中包含龙字的
for emp in Employee.query.filter(Employee.name.like('_天%')):
print(emp) 找出姓名中第二个字 带 天字的
print(emp) 找出姓名中第二个字 带 天字的
in_ / is_
for emp in db.session.query(Employee).filter(Department.name.in_(['技术部'])):
print(emp) 技术部门的员工
print(emp) 技术部门的员工
for emp in db.session.query(Employee).filter(~Department.name.in_(['技术部','财务部'])):
print(emp) 不包括技术部和财务部的员工
print(emp) 不包括技术部和财务部的员工
for emp in Employee.query.filter(Employee.name.is_('齐珍生')):
print(emp)
print(emp)
for emp in db.session.query(Employee).filter(Employee.name.startswith('刘'), Employee.gender=='男'):
print(emp) 姓刘 为男
print(emp) 姓刘 为男
导入 from sqlalchemy import and_
for emp in db.session.query(Employee).filter(and_(Employee.name.startswith('刘'), Employee.gender=='女')):
print(emp) 姓刘为女
print(emp) 姓刘为女
导入 from sqlalchemy import or_
for emp in db.session.query(Employee).filter(or_(Employee.name.startswith('刘'), Employee.name.startswith('张'))):
print(emp) 找出姓刘的和姓张的
print(emp) 找出姓刘的和姓张的
导入 from sqlalchemy import desc
for emp in db.session.query(Department).order_by(desc(Department.id)):
print(emp) 倒序排列
print(emp) 倒序排列
导入 from sqlalchemy import text
dep = db.session.query(Department).from_statement(text('select * from department where name=:n')).params(n='财务部').one() 用SQL语句查询
导入 from sqlalchemy import func
dep = db.session.query(func.count(Employee.gender),Employee.gender).group_by(Employee.gender).all()
dep
[(0, None), (131, '女'), (387, '男')]
[(0, None), (131, '女'), (387, '男')]
返回一个列表
emp = db.session.query(Department).all()
emp = db.session.query(Department)
emp.filter(Department.id > 3).all()
emp.filter(Department.id > 3).all()[0]
first() / one() 查询单个
dep = db.session.query(Department).filter(Department.id==3).first()
dep = db.session.query(Department).filter(Department.id==3333).first()
dep = db.session.query(Department).filter(Department.id==3333).one_or_none()
dep = db.session.query(Department).filter(Department.id==3).one()
scalar() 查询一列
dep = db.session.query(Department.id).filter(Department.name=='财务部').scalar()
count
dep = db.session.query(Employee).filter(Employee.name.startswith('刘')).count()
http://docs.sqlalchemy.org 官方文档
Blueprint
导入:from flask import Blueprint
定义蓝图名称:employee = Blueprint('employee', __name__)
定义类:
1.导入from flask.views import MethodView
定义类:class EmployeeListView(MethodView):
def get(self):
def get(self):
注册:app.register_blueprint(blueprint_admin, url_prefix='/admin')
wtforms
导入:from flask_wtf import Form
import wtforms
import wtforms
根据数据库表格定义类:class EmployeeForm(Form):
name = wtforms.StringField('姓名')
gender = wtforms.RadioField('性别',choices=[('男','男'), ('女','女')], default='男')
job = wtforms.StringField('职位','python')
birthdate = wtforms.DateField('生日')
idcard = wtforms.StringField('身份证号')
address = wtforms.StringField('地址')
salary = wtforms.DecimalField('工资')
department_id = wtforms.SelectField('部门')
#此处不能直接从数据库获取,因为SQLALchemy是基于app上下文运行的;写模型不要直接从数据库查
name = wtforms.StringField('姓名')
gender = wtforms.RadioField('性别',choices=[('男','男'), ('女','女')], default='男')
job = wtforms.StringField('职位','python')
birthdate = wtforms.DateField('生日')
idcard = wtforms.StringField('身份证号')
address = wtforms.StringField('地址')
salary = wtforms.DecimalField('工资')
department_id = wtforms.SelectField('部门')
#此处不能直接从数据库获取,因为SQLALchemy是基于app上下文运行的;写模型不要直接从数据库查
表单验证 from flask_wtf import Form
from wtforms import StringField, PasswordField, BooleanField, validators
class UserRegForm(Form):
username = StringField('用户名',[validators.DataRequired('用户名必填'),validators.Length(min=4,max=20,message='用户名介于4个字符到20个字符之间')])
email = StringField('邮箱',[validators.email('格式错误')])
password = PasswordField('密码',[validators.DataRequired('密码必填'),validators.Length(min=6,max=20,message='密码大于6个字符小于20个字符')])
confirm = PasswordField('重复密码',[validators.EqualTo('password',message='密码不一致')])
accept = BooleanField('接受协议',[validators.DataRequired('必须同意协议')])
from wtforms import StringField, PasswordField, BooleanField, validators
class UserRegForm(Form):
username = StringField('用户名',[validators.DataRequired('用户名必填'),validators.Length(min=4,max=20,message='用户名介于4个字符到20个字符之间')])
email = StringField('邮箱',[validators.email('格式错误')])
password = PasswordField('密码',[validators.DataRequired('密码必填'),validators.Length(min=6,max=20,message='密码大于6个字符小于20个字符')])
confirm = PasswordField('重复密码',[validators.EqualTo('password',message='密码不一致')])
accept = BooleanField('接受协议',[validators.DataRequired('必须同意协议')])
数据分页
例pms
导入 from flask.views import MethodView
定义类 class EmployeeListViews(MethodView):
def get(self,page=1):
items = Employee.query.paginate(page, per_page=10)
return render_template('admin/emp-list.html', employees=items)
def get(self,page=1):
items = Employee.query.paginate(page, per_page=10)
return render_template('admin/emp-list.html', employees=items)
视图 emp_list = EmployeeListViews.as_view('emp_list')
admin.add_url_rule('/emp/list/', view_func=emp_list, defaults={'page':1})
admin.add_url_rule('/emp/list/<int:page>/', view_func=emp_list)
admin.add_url_rule('/emp/list/', view_func=emp_list, defaults={'page':1})
admin.add_url_rule('/emp/list/<int:page>/', view_func=emp_list)
定义宏 {% macro admin_emp_list_pagat(pagination, endpint) %}
<div class="text-center">
<ul class="pagination">
<li><a href="{{ url_for(endpint, page=1) }}">首页</a></li>
{% if pagination.has_prev %}
<li><a href="{{ url_for(endpint, page=pagination.prev_num) }}">«</a></li>
{% endif %}
{% for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
<li><a href="{{ url_for(endpint, page=page) }}">{{ page }}</a></li>
{% else %}
<li class="active"><a href="#">{{ page }}</a></li>
{% endif %}
{% endif %}
{% endfor %}
{% if pagination.has_next %}
<li><a href="{{ url_for(endpint, page=pagination.next_num) }}">»</a></li>
{% endif %}
<li><a href="{{ url_for(endpint, page=pagination.pages) }}">末页</a></li>
</ul>
</div> {% endmacro %}
<div class="text-center">
<ul class="pagination">
<li><a href="{{ url_for(endpint, page=1) }}">首页</a></li>
{% if pagination.has_prev %}
<li><a href="{{ url_for(endpint, page=pagination.prev_num) }}">«</a></li>
{% endif %}
{% for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
<li><a href="{{ url_for(endpint, page=page) }}">{{ page }}</a></li>
{% else %}
<li class="active"><a href="#">{{ page }}</a></li>
{% endif %}
{% endif %}
{% endfor %}
{% if pagination.has_next %}
<li><a href="{{ url_for(endpint, page=pagination.next_num) }}">»</a></li>
{% endif %}
<li><a href="{{ url_for(endpint, page=pagination.pages) }}">末页</a></li>
</ul>
</div> {% endmacro %}
导入宏 {% import 'admin/herp.html' as herp %}
应用宏 {{ herp.admin_emp_list_pagat(employees, '.emp_list') }}
0 条评论
下一页