头图:https://cdn.naraku.cn/imgs/flask-0.jpg
摘要:简单学了一点Flask基础,记录一下。

Flask基础

  1. 客户端向服务器发起请求
  2. 服务器把请求交给Flask实例
  3. Flask实例通过Werkzeug根据URL请求与视图函数之间的对应关系来进行路由分发
  4. 根据每个URL请求,找到具体的视图函数并进行调用
    • Flask程序中路由一般是通过程序实例的装饰器实现
  5. Flask调用视图函数后,可以返回2种内容:
    • 字符串:将视图函数的返回值作为响应内容,返回给客户端
    • HTML模板内容:获得数据后,将数据传入HTML模板中,模板引擎Jinja2负责渲染数据,然后返回响应数据给客户端

      简单应用

  • 新建一个Flask项目
  • 导入Flask类

    1. # 导入Flask
    2. from flask import Flask
  • 创建实例。需要传入一个参数name,指向程序所在的模块

    1. app = Flask(__name__)
  • 配置路由。通过装饰器将路由映射到视图函数

    1. @app.route('/')
    2. def index():
    3. return 'Hello World!'
  • 完整代码 ```python

    -- coding:utf-8 --

    导入Flask

    from flask import Flask

创建实例

app = Flask(name)

路由与视图函数对应关系

@app.route(‘/‘) def index(): return ‘Hello World!’

启动程序

if name == ‘main‘: app.run()

  1. <a name="75fc7de7"></a>
  2. ## 路由
  3. <a name="3b4c5cab"></a>
  4. ### 请求方式
  5. - 使用`methods`参数指定可接受的请求方式,可指定多种,默认只接受`GET`请求
  6. ```python
  7. @app.route('/', methods=['GET','POST'])
  8. def hello():
  9. return 'Hello'

参数处理

  • 有时候需要将同一类URL映射到同一个视图函数处理,例如某个分类下不同的图书返回不同信息

    • 使用<>定义路由动态参数
    • 并且将该参数传入视图函数
      1. @app.route('/code/<book_id>')
      2. def book(book_id):
      3. print(type(book_id)) # 默认是str
      4. return f'当前书本ID为: {book_id}'
  • 有时候需要对路由做访问优化。例如上面的book_id应是int类型

    • 只需要在<>中的变量名前加上指定类型:即可
    • 若指定为int类型,则访问/code/abcstr类型的路由时会返回404 Not Found
      1. @app.route('/code/<int:book_id>')
      2. def book(book_id):
      3. print(type(book_id)) # 此时为int
      4. return f'当前书本ID为: {book_id}'

模板引擎

视图函数的作用有2个:处理业务逻辑和内容。

  • 模板其实是一个包含响应文本的文件,用变量表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
  • 使用真实值替换变量,再返回最终的字符串,这个过程称为渲染。Flask使用模板引擎Jinja2来渲染模板

返回HTML

  • 前面都是写如何返回字符串,那么如果需要返回HTML模板,则可以通过render_template实现
    • render_template()函数中第一个参数是模板文件名,后面的参数都是键值对,表示模板中变量对应的真实值 ```python

      -- coding:utf-8 --

      from flask import Flask, render_template

app = Flask(name)

@app.route(‘/‘) def index(): return render_template(‘index.html’) # templates目录下的index.html

if name == ‘main‘: app.run()

  1. <a name="457a9254"></a>
  2. ### 动态渲染
  3. - 如果需要在模板中使用某些动态的参数,则需要在视图函数中传递参数
  4. - 视图函数中通过`render_template()`函数传参
  5. - HTML模板文件中通过`{{}}`使用该变量
  6. ```python
  7. @app.route('/')
  8. def index():
  9. url = "www.naraku.cn"
  10. return render_template('index.html', url=url)
  • index.html
    1. <h1>欢迎来到: {{ url }}</h1>

用法

  • 注释:{# #}

    1. {# 这是注释 #}
    2. {# {{name}} #}
  • 控制:{% %} ```html {% if id>50 %} {{id}} => 大于50 {% elif id<50 %} {{id}} => 小于50 {% else %} {{id}} => 等于50 {% endif %}

{% for num in nums %}

当前数字为: {{num}}

{% endfor %}

  1. - 举个例子
  2. ```python
  3. def index():
  4. id = 100
  5. nums = [1, 2, 3, 4, 5]
  6. return render_template('index.html', id=id, nums=nums)

index.html

  1. {% if id>50 %}
  2. <h1>id为: {{id}} => 大于50</h1>
  3. {% elif id<50 %}
  4. <h1>id为: {{id}} => 小于50</h1>
  5. {% else %}
  6. <h1>id为: {{id}} => 等于50</h1>
  7. {% endif %}
  8. {# 注释: 上面是if,下面是for #}
  9. {% for num in nums %}
  10. <p>当前数字为: {{num}}</p>
  11. {% endfor %}

过滤器

  • 过滤器的本质是函数,有时候不仅仅只是需要输出变量的值,还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用Python中某些方法的,那么就用到了过滤器

使用方式:

  • 过滤器的使用方式:变量名 | 过滤器

    1. {{ name | filter(*args) }}
  • 如果没有任何参数传给过滤器,可以省略括号

    1. {{ name | filter }}
  • 举个例子

    1. @app.route('/')
    2. def index():
    3. name = "naraku"
    4. return render_template('index.html', name=name)
  1. {# 字符串变大写 #}
  2. <p>{{ name | upper }}</p>

链式调用

Jinja2中,过滤器支持链式调用,从左到右按顺序执行

  1. <p>{{ 'Hello World' | upper | reverse }}</p>

常用过滤器

  • format:格式化输出

    1. <p>{{ '%s' | format(name) }}</p>
  • safe:禁用转义

    1. <p>{{ '<em>hello</em>' | safe }}</p>
  • capitalize:首字母大写,其余小写

    1. <p>{{ 'hello' | capitalize }}</p>
  • upper/lower:全部转为大写或小写 ```html

    {{ ‘Hello World’ | lower }}

{{ ‘Hello World’ | upper }}

  1. - `reverse`:字符串反转
  2. ```html
  3. <p>{{ 'Hello World' | reverse }}</p>
  • truncate:字符串截断

    1. <p>{{ 'hello world' | truncate(3) }}</p>
  • striptags:渲染前把所有HTML标签删除

    1. <p>{{ '<em>hello</em>' | striptags }}</p>

Web表单

Web表单是Web程序的基本功能,它是HTML页面中负责数据采集的部件。表单中有三部分组成:表单标签、表单域、表单按钮。表单允许用户输入数据,负责HTML页面数据采集,通过表单将用户输入的数据提交给服务器。

简单示例

视图函数

  • 路由需要有GETPOST请求,需要判断请求方式

    • 路由中添加参数methods,以列表的方式传入请求方式GETPOST
    • 引入request对象,获取请求方式及参数

      1. @app.route("/", methods=['GET', 'POST'])
      2. def index():
      3. # 获取请求方式
      4. if request.method == "POST":
      5. # 获取请求参数
      6. username = request.form.get('username')
      7. password = request.form.get('password')
      8. password2 = request.form.get('password2')
      9. # 判断参数是否完整
      10. if not all([username, password, password2]):
      11. print("参数不完整")
      12. elif password != password2:
      13. print("密码不一致")
      14. else:
      15. return "success"
      16. return render_template("index.html")
  • 模板文件

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>WTF</title>
    6. </head>
    7. <body>
    8. <form method="post">
    9. <label>用户名:</label><input type="text" name="username"><br>
    10. <label>密码:</label><input type="password" name="password"><br>
    11. <label>确认密码:</label><input type="password" name="password2"><br>
    12. <input type="submit" value="提交"><br>
    13. </form>
    14. </body>
    15. </html>

Flash消息闪现

  • 有时候需要向模板动态传递一些消息,例如提示用户名不能为空、密码不一致等等,可以通过flash库实现
    • 引入flash
    • 设置密钥Secret_key ```python from flask import Flask, render_template, request, flash

app = Flask(name)

@app.route(“/“, methods=[‘GET’, ‘POST’]) def index(): if request.method == “POST”: username = request.form.get(‘username’) password = request.form.get(‘password’) password2 = request.form.get(‘password2’)

  1. # 向模板传递消息
  2. if not all([username, password, password2]):
  3. flash("参数不完整")
  4. elif password != password2:
  5. flash("密码不一致")
  6. else:
  7. return "success"
  8. return render_template("index.html")

if name == ‘main‘: app.run()

  1. - 模板文件通过`get_flashed_messages()`函数获取消息并渲染
  2. ```html
  3. <body>
  4. <form method="post">
  5. <label>用户名:</label><input type="text" name="username"><br>
  6. <label>密码:</label><input type="password" name="password"><br>
  7. <label>确认密码:</label><input type="password" name="password2"><br>
  8. <input type="submit" value="提交"><br>
  9. {# 通过遍历函数获取消息 #}
  10. {% for msg in get_flashed_messages() %}
  11. {{ msg }}
  12. {% endfor %}
  13. </form>
  14. </body>
  • 此时直接启动程序,会出现报错,原因是因为未设置密钥Secret_key

小记 - Flask - 图1

  • flash希望对需要输出的内容进行加密,因此需要设置密钥,作加密消息的混淆。
    • 只需要一行代码,给app.secret_key赋值即可 ```python from flask import Flask, render_template, request, flash

app = Flask(name) app.secret_key = “naraku” # 设置密钥

….

  1. - 如果使用**Python2**进行开发,可能会遇到`UnicodeDecodeError`等编码的问题,只需要在中文字符前面加个`u`进行转码即可
  2. ```python
  3. @app.route("/", methods=['GET', 'POST'])
  4. def index():
  5. if request.method == "POST":
  6. username = request.form.get('username')
  7. password = request.form.get('password')
  8. password2 = request.form.get('password2')
  9. # 向模板传递消息
  10. if not all([username, password, password2]):
  11. flash(u"参数不完整") # 这里加个u
  12. elif password != password2:
  13. flash(u"密码不一致")
  14. else:
  15. return "success"
  16. return render_template("index.html")

过滤

  • 有时需要在不同的地方显示不同信息
    • flash()接收2个参数,通过指定第2个参数category,并在前端通过category_filter=["分类名"]过滤调用
      1. if open_form.submit.data and open_form.validate_on_submit():
      2. pill_key = request.form.get('pill_key')
      3. flash(f"Open表单提交成功: {pill_key}", category="open")
      4. elif find_form.submit.data and find_form.validate_on_submit():
      5. find_email = request.form.get('find_email')
      6. flash(f"Find表单提交成功: {find_email}", category="find")
  1. {% for msg in get_flashed_messages(category_filter=["find"]) %}
  2. {{ msg }} <br>
  3. {% endfor %}

插件-表单-WTF

在Flask中,为了处理Web表单,一般使用Flask-WTF扩展,它封装了WTForms,并且验证表单数据的功能。

  • 使用Flask-WTF需要配置密钥参数SECRET_KEY必须开启**CSRF_token**
  • CSRF_ENABLED可以防止CSRF,SECRET_KEY用于生成加密令牌。CSRF防护会根据设置的密钥生成加密令牌
  • 需要先安装此插件
    1. pip install Flask-WTF

基本示例

  • 先自定义一个表单类
    • 继承自基类FlaskForm
    • 导入所需的表单字段 ```python from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField

app = Flask(name) app.secret_key = “naraku”

class RegForm(FlaskForm): username = StringField(“账号:”) password = PasswordField(“密码:”) password2 = PasswordField(“确认密码:”) submit = SubmitField(“提交”)

  1. - 传递到模板
  2. ```python
  3. @app.route("/reg", methods=['GET', 'POST'])
  4. def reg():
  5. reg_form = RegForm()
  6. return render_template("index.html", reg_form=reg_form)
  • 前端渲染

    1. <body>
    2. <form method="post">
    3. {{ reg_form.username.label }} {{ reg_form.username }} <br>
    4. {{ reg_form.password.label }} {{ reg_form.password }} <br>
    5. {{ reg_form.password2.label }} {{ reg_form.password2 }} <br>
    6. {{ reg_form.submit }}
    7. </form>
    8. </body>
  • 完整代码 ```python

    -- coding:utf-8 --

from flask import Flask, render_template, request, flash from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField

app = Flask(name) app.secret_key = “naraku”

class RegForm(FlaskForm): username = StringField(“账号:”) password = PasswordField(“密码:”) password2 = PasswordField(“确认密码:”) submit = SubmitField(“提交”)

@app.route(“/reg”, methods=[‘GET’, ‘POST’]) def reg(): reg_form = RegForm() return render_template(“index.html”, reg_form=reg_form)

if name == ‘main‘: app.run()

  1. <a name="6cc7dc63"></a>
  2. ### 表单验证
  3. - 引入验证函数,并在表单类中实现
  4. - **必须开启**`**CSRF_token**`,否则验证失败
  5. - 通过`validators`传递需要调用的函数,可以为一个列表
  6. - `DataRequired()`,判断字段是否非空
  7. - `EqualTo()`,判断当前字段与目标字段是否相等。第1个参数为目标字段,第2个参数为错误消息
  8. ```python
  9. from wtforms.validators import DataRequired, EqualTo
  10. class RegForm(FlaskForm):
  11. username = StringField("账号:", validators=[DataRequired()])
  12. password = PasswordField("密码:", validators=[DataRequired()])
  13. password2 = PasswordField("确认密码:", validators=[DataRequired(), EqualTo("password", "密码不一致")])
  14. submit = SubmitField("提交")
  • 表单验证

    • 通过表单对象.validate_on_submit()函数一行实现表单验证 ```python @app.route(“/reg”, methods=[‘GET’, ‘POST’]) def reg(): reg_form = RegForm() # 创建一个表单对象

    获取请求方式

    if request.method == “POST”:

    获取请求参数

    username = request.form.get(‘username’) password = request.form.get(‘password’) password2 = request.form.get(‘password2’)

    表单验证

    if reg_form.validate_on_submit():

    1. return "Success"

    else:

    1. pass

    return render_template(“index.html”, reg_form=reg_form) ```

  • 前端开启CSRF_token

    • 通过调用对象名.csrf_token()函数开启

      1. <body>
      2. <form method="post">
      3. {# 开启CSRF_token #}
      4. {{ reg_form.csrf_token() }}
      5. {{ reg_form.username.label }} {{ reg_form.username }} <br>
      6. {{ reg_form.password.label }} {{ reg_form.password }} <br>
      7. {{ reg_form.password2.label }} {{ reg_form.password2 }} <br>
      8. {{ reg_form.submit }}<br>
      9. {# Flash消息 #}
      10. {% for msg in get_flashed_messages() %}
      11. {{ msg }}
      12. {% endfor %}
      13. </form>
      14. </body>
  • 完整代码 ```python

    -- coding:utf-8 --

from flask import Flask, render_template, request, flash from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField from wtforms.validators import DataRequired, EqualTo

app = Flask(name) app.secret_key = “naraku”

class RegForm(FlaskForm): username = StringField(“账号:”, validators=[DataRequired()]) password = PasswordField(“密码:”, validators=[DataRequired()]) password2 = PasswordField(“确认密码:”, validators=[DataRequired(), EqualTo(“password”, “密码不一致”)]) submit = SubmitField(“提交”)

@app.route(“/reg”, methods=[‘GET’, ‘POST’]) def reg(): reg_form = RegForm()

  1. # 获取请求方式
  2. if request.method == "POST":
  3. # 获取请求参数
  4. username = request.form.get('username')
  5. password = request.form.get('password')
  6. password2 = request.form.get('password2')
  7. # 表单验证
  8. if reg_form.validate_on_submit():
  9. return "success"
  10. else:
  11. flash("参数有误")
  12. return render_template("index.html", reg_form=reg_form)
  13. if __name__ == '__main__':
  14. app.run(debug=True)
  1. <a name="1936afac"></a>
  2. ### 常用字段
  3. | 字段对象 | 说明 |
  4. | --- | --- |
  5. | StringField | 文本字段 |
  6. | TextAreaField | 多行文本字段 |
  7. | PasswordField | 密码字段 |
  8. | HiddenField | 隐藏文件字段 |
  9. | DateField | 文本字段,值为 `datetime.date`<br /> 文本格式 |
  10. | DateTimeField | 文本字段,值为 `datetime.datetime`<br /> 文本格式 |
  11. | IntegerField | 文本字段,值为整数 |
  12. | DecimalField | 文本字段,值为`decimal.Decimal` |
  13. | FloatField | 文本字段,值为浮点数 |
  14. | BooleadnField | 复选框,`True`<br />/`False` |
  15. <a name="6114e108"></a>
  16. ### 常用验证函数
  17. | 验证函数 | 说明 |
  18. | --- | --- |
  19. | `DataRequired` | 确保字段中有数据 |
  20. | `EqualTo` | 比较两个字段的值,常用于判断两次密码是否一致 |
  21. | `Length` | 验证输入的字符串长度 |
  22. | `NumberRange` | 验证输入的数值范围 |
  23. | `URL` | 验证URL |
  24. | `AnyOf` | 验证输入值在可选列表中 |
  25. | `NoneOf` | 验证输入值不在可选列表中 |
  26. <a name="cc09f939"></a>
  27. ## 插件-数据库-SQLAlchemy
  28. - `SQLAlchemy`是一个关系型数据库框架,它提供了高层ORM和底层的原生数据库操作,`Flask-sqlalchemy`是一个简化了的`SQLAlchemy`操作的扩展。`SQLAchemy`实际上是对数据库的抽象,让开发者不用直接和SQL语句打交道,而是通过Python对象来操作数据库。
  29. - 安装`Flask-sqlalchemy`
  30. ```shell
  31. pip install flask-sqlalchemy
  • 如果需要操作Mysql,还需要安装mysqldb
    1. pip install flask-mysqldb

管理数据库

  • Flask-SQLAlchemy中,数据库使用URL指定,而且程序使用的数据库必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中

    • 数据库类型://数据库账号:密码@地址:端口/数据库名
      1. app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@127.0.0.1:3306/flask'
  • 其它设置

    1. # 动态追踪修改设置,如未设置只会提示警告,不建议开启
    2. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

创建数据库对象

  • 引入相关库,配置app对象的数据库信息,创建数据库对象,并传入当前app对象 ```python from flask import Flask from flask_sqlalchemy import SQLAlchemy

app = Flask(name) app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘mysql://root:root@127.0.0.1:3306/flask_demo’ app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False db = SQLAlchemy(app)

  1. - 创建一个数据库,打开命令行登录数据库后输入
  2. ```sql
  3. create database flask_demo charset=utf8;

数据模型

  • 定义数据模型 | Roles表 | | | —- | —- | | role_id(
    主键) | | | 1 | 管理员 | | 2 | 普通用户 |
Users表
user_id user_name role_id
(外键)
1 1号管理 1
2 2号管理 1
3 用户A 2
  • 实现数据模型
    • 通过class实现,继承自db.Model
    • 定义表名:__tablename__
    • 定义字段:db.Column(字段类型, 列选项)
    • 指定外键:db.ForeignKey('表名.列名') ```python class Role(db.Model):

      定义表名

      tablename = ‘roles’

      定义字段

      id = db.Column(db.Integer, primary_key=True) # 主键 name = db.Column(db.String(16), unique=True) # 唯一

class User(db.Model): tablename = ‘users’ id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(16), unique=True) role_id = db.Column(db.Integer, db.ForeignKey(‘roles.id’)) # 外键

  1. - 创建表
  2. ```python
  3. if __name__ == '__main__':
  4. # db.drop_all() # 删除表
  5. db.create_all() # 新建表
  6. # app.run()

小记 - Flask - 图2

基本操作

  • 增删改操作,由数据库会话db.session管理
    • 在准备把数据写入数据库前,要先将数据添加到会话中,然后调用db.session.commit()方法提交会话
  • 查询操作,通过query对象进行操作
    • 最基本的查询是返回表中所有数据,可以通过过滤器进行更精确的数据库查询

增删改

  1. if __name__ == '__main__':
  2. # db.drop_all() # 删除表
  3. # db.create_all() # 新建表
  4. # 增加
  5. # Role表增加用户
  6. role = Role(name='admin') # 创建一个对象
  7. db.session.add(role) # 将添加对象加入会话
  8. db.session.commit() # 将会话提交到数据库
  9. # User表增加用户
  10. # 此时role对象的id为1,所以创建的user是管理员权限
  11. user = User(name='naraku', role_id=role.id)
  12. db.session.add(user)
  13. db.session.commit()
  14. # app.run()
  15. # 修改
  16. # 前面已经把user对象添加到db.session()中,因此不需要再次添加
  17. user.name = 'miroku'
  18. db.session.commit()
  19. # 删除
  20. db.session.delete(user)
  21. db.session.commit()

小记 - Flask - 图3

  • 其它语句
    1. db.session.add(role) # 添加到数据库的session中
    2. db.session.add_all([user1, user2]) # 以列表形式添加多个
    3. db.session.rollback() # 回滚操作
    4. db.session.delete(user) # 删除数据
    5. db.session.commit() # 提交到数据库

查询

简单应用
  • 先建表并添加数据 ```python

    -- coding:utf-8 --

from flask import Flask from flask_sqlalchemy import SQLAlchemy

app = Flask(name) app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘mysql://root:root@127.0.0.1:3306/flask_demo’ app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False db = SQLAlchemy(app)

class Role(db.Model): tablename = ‘roles’ id = db.Column(db.Integer, primary_key=True) # 主键 name = db.Column(db.String(16), unique=True) # 唯一 users = db.relationship(‘User’, backref=’role’)

class User(db.Model): tablename = ‘users’ id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(16), unique=True) email = db.Column(db.String(16), unique=True) role_id = db.Column(db.Integer, db.ForeignKey(‘roles.id’)) # 外键

  1. def __repr__(self):
  2. return f'<User: {self.id}, {self.name}, {self.email}>'

@app.route(‘/‘) def index(): return ‘Hello SQLAlchemy’

if name == ‘main‘: db.drop_all() # 删除表 db.create_all() # 新建表

Role表

  1. role1 = Role(name='Admin') # 管理员
  2. role2 = Role(name='Guest') # 普通用户
  3. db.session.add_all([role1, role2])
  4. db.session.commit()
  5. # User表
  6. user1 = User(name='naraku',email='naraku@qq.com' , role_id=role1.id)
  7. user2 = User(name='zhang',email='zhang@qq.com' , role_id=role2.id)
  8. user3 = User(name='chen',email='chen@qq.com' , role_id=role2.id)
  9. user4 = User(name='zhou',email='zhou@qq.com' , role_id=role2.id)
  10. user5 = User(name='tang',email='tang@qq.com' , role_id=role2.id)
  11. user6 = User(name='wu',email='wu@qq.com' , role_id=role2.id)
  12. user7 = User(name='qian',email='qian@qq.com' , role_id=role2.id)
  13. user8 = User(name='liu',email='liu@qq.com' , role_id=role2.id)
  14. user9 = User(name='li',email='li@qq.com' , role_id=role2.id)
  15. user10 = User(name='sun',email='sun@qq.com' , role_id=role2.id)
  16. db.session.add_all([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10])
  17. db.session.commit()
  1. ![](https://cdn.nlark.com/yuque/0/2020/jpeg/520228/1608494105482-e69bfa7b-6594-4c38-b999-5237258eb6ee.jpeg#crop=0&crop=0&crop=1&crop=1&height=654&id=uf0M2&originHeight=654&originWidth=1241&originalType=binary&ratio=1&rotation=0&showTitle=false&size=0&status=done&style=none&title=&width=1241)
  2. - 这里借助`ipython`这个库,可以直接在`Pycharm`下方的`Terminal`终端调用进行查询。如果没有`ipython`的可通过`File-> setting-> Project Interpreter`进行安装
  3. - 安装完成后在`Terminal`输入`ipython`进入,并导入当前文件全部代码
  4. ```shell
  5. > ipython
  6. IN [1]: from demo import *

小记 - Flask - 图4

  • 开始查询操作 ```shell

    查询全部用户

    User.query.all()

    查询用户总数

    User.query.count()

    查询第1个用户

    User.query.first()

查询id为4的用户

因为id是主键,可通过执行器get查询

User.query.get(4)

通过过滤器查询

User.query.filter_by(id=4).first() User.query.filter(User.id==4).first()

  1. ![](https://cdn.nlark.com/yuque/0/2020/jpeg/520228/1608494105483-82e4da74-9b7d-4deb-9c3b-ebdafb1f1bd1.jpeg#crop=0&crop=0&crop=1&crop=1&height=878&id=hurPu&originHeight=878&originWidth=1373&originalType=binary&ratio=1&rotation=0&showTitle=false&size=0&status=done&style=none&title=&width=1373)
  2. <a name="cc525323"></a>
  3. ##### 查询执行器
  4. `表模型名.query.方法()`
  5. | 方法 | 说明 |
  6. | --- | --- |
  7. | `all()` | 以列表形式返回查询的所有结果 |
  8. | `first()` | 返回查询的第一个结果,如未查到,返回None |
  9. | `first_or_404()` | 返回查询的第一个结果,如未查到,返回404 |
  10. | `get()` | 返回指定主键对应的行,如不存在,返回None |
  11. | `get_or_404()` | 返回指定主键对应的行,如不存在,返回404 |
  12. | `count()` | 返回查询结果的数量 |
  13. | `paginate()` | 返回一个Paginate对象,它包含指定范围内的结果 |
  14. <a name="333bd245"></a>
  15. ##### 查询过滤器
  16. | 过滤器 | 说明 |
  17. | --- | --- |
  18. | `filter(对象.属性==值)` | 把过滤器添加到原查询上,返回一个新查询。支持比较运算符 |
  19. | `filter_by(属性=值)` | 把等值过滤器添加到原查询上,返回一个新查询 |
  20. | `limit` | 使用指定的值限定查询返回结果 |
  21. | `offset()` | 偏移原查询返回的结果 |
  22. | `order_by()` | 根据指定条件对原查询进行排序,返回一个新查询 |
  23. | `group_by()` | 根据指定条件对原查询进行分组,返回一个新查询 |
  24. <a name="69851aa1"></a>
  25. ### 关系引用
  26. 有时候需要一些属性方便查询数据,但是这些属性不能出现在数据库的字段中
  27. - `relationship()``sqlalchemy`对关系之间提供的一种便利的调用方式,关联不同的表
  28. - 1个参数:对象模型名。指需要关联的对象,可在`Role`类的实例中通过`role.users`查看该实例在`User`模型中的属性
  29. - `backref`参数:对关系提供**反向引用**的声明。可在`User`类的实例中通过`user.role`查看该实例在`Role`模型中的属性
  30. ```python
  31. class Role(db.Model):
  32. __tablename__ = 'roles'
  33. id = db.Column(db.Integer, primary_key=True) # 主键
  34. name = db.Column(db.String(16), unique=True) # 唯一
  35. # 关键代码
  36. users = db.relationship('User', backref='role')
  37. class User(db.Model):
  38. __tablename__ = 'users'
  39. id = db.Column(db.Integer, primary_key=True)
  40. name = db.Column(db.String(16), unique=True)
  41. role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) # 外键
  • 完整代码
    • __repr__(self):输出某个实例化对象时的回显 ```python from flask import Flask from flask_sqlalchemy import SQLAlchemy

app = Flask(name) app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘mysql://root:root@127.0.0.1:3306/flask_demo’ app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’] = False db = SQLAlchemy(app)

class Role(db.Model): tablename = ‘roles’ id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(16), unique=True)

  1. # 关键代码
  2. users = db.relationship('User', backref='role')
  3. def __repr__(self):
  4. return f'<Role: {self.name}, {self.id}>'

class User(db.Model): tablename = ‘users’ id = db.Column(db.Integer, primarykey=True) name = db.Column(db.String(16), unique=True) roleid = db.Column(db.Integer, db.ForeignKey(‘roles.id’)) # 外键 def __repr(self): return f’

@app.route(‘/‘) def index(): return ‘Hello SQLAlchemy’

if name == ‘main‘: db.drop_all() # 删除表,防止测试时数据冗余 db.create_all() # 新建表 role = Role(name=’admin’) db.session.add(role) db.session.commit()

  1. user1 = User(name='naraku', role_id=role.id)
  2. user2 = User(name='miroku', role_id=role.id)
  3. db.session.add_all([user1, user2])
  4. db.session.commit()
  5. print(role.users) # 查看Role实例在User表中的属性
  6. print(user1.role) # 查看User实例在Role表中的属性
  7. print(user2.role)
  1. <a name="0613b887"></a>
  2. ### 常见字段
  3. - `db.字段名`
  4. | 类型名 | Python数据类型 | 说明 |
  5. | --- | --- | --- |
  6. | `Integet` | `int` | 普通整数,一般是32位 |
  7. | `SmallInteget` | `int` | 取值范围小的整数,一般是16位 |
  8. | `BigInteget` | `int/long` | 不限制精度的 |
  9. | `Float` | `float` | 浮点数 |
  10. | `Numeric` | `decimal.Decimal` | 普通整数,一般是32位 |
  11. | `String` | `str` | 变长字符串 |
  12. | `Text` | `str` | 变长字符串,对较长或不限长度的字符串做了优化 |
  13. | `Unicode` | `unicode` | 变长Unicode字符串 |
  14. | `UnicodeText` | `unicode` | 变长Unicode字符串,对较长或不限长度的字符串做了优化 |
  15. | `Boolean` | `bool` | 布尔值 |
  16. | `Date` | `datetime.date` | 时间 |
  17. | `Time` | `datetime.datetime` | 日期和时间 |
  18. | `LargeBinary` | `str` | 二进制文件 |
  19. <a name="b043fc3a"></a>
  20. ### 常见列选项
  21. | 选项名 | 说明 |
  22. | --- | --- |
  23. | `primary_key` | 主键。若为`True`<br />,即为表的主键 |
  24. | `unique` | 唯一。若为`True`<br />,即此列不允许出现重复的值 |
  25. | `default` | 默认值。为此列定义默认值 |
  26. | `index` | 索引。若为`True`<br />,为此列创建索引,提高查询效率 |
  27. | `nullable` | 非空。若为`True`<br />,允许为空,反之不允许为空 |
  28. <a name="a8d14911"></a>
  29. ## 依赖包
  30. ```shell
  31. $ pip freeze > requirements.txt # 输出依赖包及版本到文本
  32. $ pip install -r requirements.txt # 安装依赖包