2019-03-26 Flask大纲

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>

  • 配置数据库信息

  • 映射

    • 创建: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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容