flask
环境
使用virtualenv创建
安装:pip install virtualenv
创建虚拟环境:virtualenv --no-site-packages -p python.exe的绝对路径(也可以不写) 环境名
-
激活环境
win:cd 环境名/Scripts 执行activate
Linux/Mac:source activate
退出环境:deactivate
使用pycharm创建
进入setting下面的project interpreter页面,选择框里面的show all,旁边有个'+'号,点击创建虚拟环境,不继承全局的包(site-packages)
进入setting下面的project interpreter页面,选择框里面的show all,旁边有个'+'号,如果通过dos命令已经创建了环境就选择Existing enviroment,在本地文件夹中选择环境
flask安装
安装:先激活环境,再执行pip install flask
pip使用
查询安装的库:pip list / pip freeze
安装内容:pip install xxx
同时安装多个文件:pip install -r requirement.txt (创建一个requirement.txt文件,在里面编辑要安装的文件,一个文件占一行)
flask使用
from flask import Flask
创建app对象 app = Flask(name) @app.route('路由地址') def 函数名(形参列表): 函数体 return 值
app.run() 在Terminal窗口,虚拟环境下输入python 要执行的文件名.py
启动
flask自带启动方式:app.run(host='ip地址', port=端口号, debug=True/False)
使用flask-script库
pip install flask-script
from flask_script import Manager manager = Manager(app) manager.run()
在Terminal启动命令:python xxx.py runserver -p -h -d
路由规则
定义格式:<转换器(类型):参数名>
转换器
int:指定整型
string:指定字符串,默认类型
float:指定浮点类型
注意:string:name和<name>是一样的
请求与响应
请求
-
获取参数
GET请求:获取参数:request.args['key']、request.args.get('key')(推荐 .get的方式)
POST请求参数:request.form['key']、request.form.get('key')(推荐 .get的方式)
获取多个同样的key对应的value时,使用getlist('key')
获取请求路径:request.path
请求cookies:request.cookies
获取上传文件:request.files 取值:request.files.get('key')、request.files['key']
-
使用debug!!!
- 获取debug里面request数据:先按下debug键,再在获取参数的代码行标红点,载通过postman传递参数,这样就可以操作debug控制台的Console和Debugger了!!!
响应
导包:from flask import make_response
使用:make_response('响应内容', 响应状态码)
cookie与session
cookie
产生场景:由于HTTP无状态协议,cookie的使用,保存一个令牌(标识符)用于标识用户的登录状态
令牌的产生:在登录时向cookie中设置的
设置令牌:res = make_response() res.set_cookie('key', 'value', max_age)
cookie不能跨浏览器
cookie中设置的参数有字节限制,不能无限的存储参数
删除:res = make_response() res.delete_cookie('key')
session
-
flask默认存储session的形式,将session数据保存在客户端
导包:from flask import session
使用:session['key']='value'
-
使用flask-session库,将session数据保存在服务器端
pip install redis pip install flask-session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.Redis(host='', port=6379)
加密复杂程度,加密,加密复杂程度和设值有关 app.secret_key = 'value'
from flask_session import Session Session(app)
装饰器
条件
外层函数嵌套内层函数
外层函数返回内层函数
内层函数调用外层函数的参数
注意
外层函数传入的参数即为被装饰的函数
from functools import wraps @wraps(func)
@function
def test(*args, **kwargs): pass 定义加上装饰器的函数的时候,装饰器就被调用 这时test = function(test)
蓝图
产生背景:管理路由地址
安装:pip install flask-blueprint
使用
from flask import Blueprint 第一步:blue = Blueprint('first', name) @blue.route('路由地址')
第二步:flask对象app.register_blueprint(blueprint=blue)
跳转
-
有参跳转
- redirect(url_for('生成蓝图的第一个参数.跳转的函数名称', 参数名=值,参数名2=值2))
-
无参跳转
- redirect(url_for('生成蓝图的第一个参数.跳转的函数名称'))
模板
父模板
定义网站模板的大体框架,可以被动态填充内容的block块
block块定义: {% block name %} {% endblock %}
注意:block名称不能取同名
子模板
继承父模板: {% extends '父模板' %}
动态可选择性的填充父模板中定义的block块,使用{% block name %}动态内容{% endblock %}
语法
-
解析标签:{% 标签名 %} {% end标签名 %}
for:{% for a in [] %} 内容 {% else %} 内容 {% endfor %}
if:[% if 判断条件 %} 内容 {% else %} 内容 {% endif %}
block:{% block name %} {% endblock %}
-
解析变量:{{ 变量名 }}
-
loop:变量
loop.index0:从0开始
loop.revindex:逆序到1结束
loop.revindex0:逆序到0结束
loop.first:第一次循环返回True
loop.last:最后一次循环返回True
-
注解:{# 注解内容 #}
-
过滤器
写法:{{ 变量 | 过滤器 }}
safe:转换成对应的标签
striptags:不解析成标签
length
upper
......
-
反向解析路由/地址
解析路由: href="{{ url_for('生成蓝图的第一个参数.跳转的函数名称') }}"
解析地址: <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
模型
ORM概念:object relationship mapping,对象关系映射
flask-sqlalchemy库
安装:pip install flask-sqlalchemy
-
创建模型
"""==========zhuming=========="""
from flask_sqlalchemy import SQLAlchemy
生成SQLAlchemy数据库访问对象db
db = SQLAlchemy()
继承了db.Model的类就是一个表
class Student(db.Model): # 定义id主键,自增字段 id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 定义不能为空且唯一的姓名字段 s_name = db.Column(db.String(10), unique=True, nullable=False) # 定义整型,默认为20的年龄字段 age = db.Column(db.Integer, default=20)
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n240" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">tablename = 'stu'
def save(self):保存与修改
db.session.add(self)
db.session.commit()
def delete(self):删除
db.session.delete(self)
db.session.commit()</pre><pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n242" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">#去了解一下
def init(self):
pass
def new(cls, *args, **kwargs):
pass
def del(self):
pass</pre>
class Teacher(db.Model): tea_id = db.Column(db.Integer, primary_key=True, autoincrement=True) tea_name = db.Column(db.String(10), unique=True, nullable=False) tea_age = db.Column(db.Integer, default=22)
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n244" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">tablename = 'teacher'</pre>
-
配置数据库信息
数据库连接格式: flask对象app app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:password@host:port/database' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
sqlalchemy对象db.init__app(flask对象)
-
映射
创建:sqlalchemy对象db.create_all()
删除:sqlalchemy对象db.drop_all()
增
- db.session.add(对象) db.session.commit()
删
- db.session.delete(对象) db.session.commit()
改
- db.session.add(对象) db.session.commit()
查
1、模型名.query就是先从数据库中取到所有数据 2、模型名.query.first(),返回所有数据中的第一条 3、模型名.query.all(),返回所有数据 4、模型名.query.filter().all(),就是从数据库中取到所有数据之后,通过filter条件进行过滤(筛选),然后把过滤过后的所有数据返回
注意:所以要理清query和filter()过滤器在查询数据中扮演的角色,然后就可以灵活运用了,这个很重要!!!
query:管理器
模型名.query.filter(模型名.字段 == 值)
模型名.query.filter_by(字段 = 值)
模型名.query.first():查询结果中的第一个数据对象
模型名.query.all():查询结果中的所有对象,返回列表
模型名.query.get():查询主键所在行的对象信息
-
order_by():排序 和filter()的位置可以灵活处理
-
sqlalchemy 1.3版本之前写法
升序:order_by('字段')
降序:order_by('-字段')
-
sqlalchemy 1.3版本
升序:order_by(模型名.字段)
降序:order_by(-模型名.字段)
-
-
offset/limit:分页 和切片分页
模型名.query.offset((page-1)*N).limit(N).all()
数据 = 模型名.query.all() 数据[(page-1)N : pageN]
-
模糊查询
模型名.query.filter(模型.字段.contains('值')).all()
-
like % _
- 模型名.query.filter(模型名.字段.like('%值_')).all()
-
startswith
- 模型名.query.filter(模型名.字段.startswith('值')).all()
-
endswith
- 模型名.query.filter(模型名.字段.endswith('值')).all()
-
in/notin
- 模型名.query.filter(模型名.字段.in([值1, 值2, ...])).all() 模型名.query.filter(模型名.字段.notin([值1, 值2, ...])).all()
-
大于:gt 大于等于:ge
- 模型名.query.filter(模型名.字段.gt(值)).all() 模型名.query.filter(模型名.字段 > 值).all()
小于:lt 小于等于:le
-
and、or、not_
from sqlalchemy import and, or, not_ 模型名.query.filter(and_(多个条件用逗号隔开)).all()
条件并列可以直接: 模型名.query.filter(条件1,条件2,...).all()
关联关系
一对多
-
定义:
class Grade(db.Model): # 自增的主键id id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 定义不能为空,且唯一的班级名称字段 g_name = db.Column(db.String(10), nullable=False, unique=True) stus = db.relationship('Student', backref='p', lazy=True)
继承了db.Model的类就是一个模型(对应数据库的表)
class Student(db.Model): # 定义id主键,自增字段 id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 定义不能为空且唯一的姓名字段 s_name = db.Column(db.String(10), unique=True, nullable=False) # 定义整型,默认为20的年龄字段 age = db.Column(db.Integer, default=20) # 定义的关联班级表id的外键g_id g_id = db.Column(db.Integer, db.ForeignKey('grade.id'), nullable=True)
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n359" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit;">tablename = 'stu'</pre>
重点在班级表中关联关系的定义: stus = db.relationship('Student', backref='p', lazy=True)
班级查询学生:班级对象.stus
学生查询班级:学生对象.backref
多对多
-
定义:
class Student(db.Model): # 定义id主键,自增字段 id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 定义不能为空且唯一的姓名字段 s_name = db.Column(db.String(10), unique=True, nullable=False) # 定义整型,默认为20的年龄字段 age = db.Column(db.Integer, default=20) # 定义的关联班级表id的外键g_id g_id = db.Column(db.Integer, db.ForeignKey('grade.id'), nullable=True)
class Student(db.Model):
# 定义id主键,自增字段
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# 定义不能为空且唯一的姓名字段
s_name = db.Column(db.String(10), unique=True, nullable=False)
# 定义整型,默认为20的年龄字段
age = db.Column(db.Integer, default=20)
# 定义的关联班级表id的外键g_id
g_id = db.Column(db.Integer, db.ForeignKey('grade.id'), nullable=True)
tablename = 'stu'
def save(self):
# 保存与修改
db.session.add(self)
db.session.commit()
def delete(self):
# 删除
db.session.delete(self)
db.session.commit()
c_s = db.Table('c_s', db.Column('s_id', db.Integer, db.ForeignKey('stu.id')), db.Column('c_id', db.Integer, db.ForeignKey('course.id')) )
class Course(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) c_name = db.Column(db.String(10), nullable=False, unique=True) # 关系中的lazy参数值dynamic,通过班级对象.stus的方法获取学生对象的时候,是返回 查询对象,可以进行filter()过滤和all()或者first()取值 stus = db.relationship('Student', secondary=c_s, backref='cou', lazy='dynamic')
多对多可以任意选择一个表添加关联关系: stus = db.relationship('Student', secondary=c_s, backref='cou', lazy=True)
学生查询课程:学生对象.backref
课程查询学生:课程对象.stus
添加和删除:append/remove