Flask-03-Jinja2模板引擎、过滤器、模板继承、解决csrf攻击、数据库操作(ORM,Flask-SQLAlchemy)、数据表操作(增删改查)

一、Jinja2模板引擎

Flask内置的模板语言,它的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能。
渲染模版函数

  • Flask提供的 render_template 函数封装了该模板引擎
  • render_template 函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的真实值。

1.模板基本使用

(1)在flask应用对象创建的时候,设置或者保留template_folder参数,创建模板目录

app = Flask(__name__,template_folder='templates')

(2)在项目下创建 templates 文件夹,用于存放所有的模板文件,并在目录下创建一个模板html文件 index1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>{{title}}</h1>
    <p>num={{num}}</p>
</body>
</html>

(3)在视图函数设置渲染模板并设置模板数据


from flask import Flask,render_template

app = Flask(__name__, template_folder='templates')

@app.route('/')
def index():
    data = {}
    data['title'] = '我的第一个flask网页'
    data['num'] = 100
    return render_template('index1.html', **data)


if __name__ == '__main__':
    app.run(debug=True)

输出变量

{{}} 来表示变量名,这种 {{}} 语法叫做 变量代码块

使用 {# #} 进行注释,注释的内容不会在html中被渲染出来

{# {{ name }} #}

2.模板语句

主程序:


from flask import Flask, render_template

app = Flask(__name__, template_folder='templates')

@app.route('/')
def index():
    data = {}
    data['info'] = {
        'name': 'xiaoming',
        'age': 19,
        'sex': True,
        'class': '1009'
    }
    data['student_list'] = ['xiaoming', 'xiaobai', 'xiaohei', 'xiaoan']

    data['goods_list'] = [
        {'id': 10, 'name': 'Python7天入门到放弃', 'price': 99.9, 'num': 100},
        {'id': 11, 'name': 'Python3天入门到放弃', 'price': 99.9, 'num': 100},
        {'id': 12, 'name': 'Python5天入门到放弃', 'price': 99.9, 'num': 100},
        {'id': 13, 'name': 'Go7天入门到放弃', 'price': 99.9, 'num': 100},
        {'id': 14, 'name': 'Go5天入门到放弃', 'price': 99.9, 'num': 100},
        {'id': 15, 'name': 'Linux7天入门到放弃', 'price': 99.9, 'num': 100},
    ]

    return render_template('index2.html', **data)


if __name__ == '__main__':
    app.run(debug=True)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <p>访问字典数据中的成员</p>
    <p>{{ info['name'] }}</p>
    <p>{{ info.name }}</p>

    <p>访问列表数中的成员,点语法不支持负数下标</p>
    <p>{{ student_list.0 }}</p>
    <p>{{ student_list.2 }}</p>
    <p>{{ student_list[-1] }}</p>
    <p>{{ student_list[2] }}</p>

    <p>if判断</p>
    {% if info.age < 18 %}
        <p>小明请出去</p>
    {% endif %}

    {% if info.age > 10 %}
        <p>小明同学</p>
    {% else %}
        <p>小明小朋友</p>
    {% endif %}

    {% if info.age < 10 %}
        <p>小明小朋友</p>
    {% elif info.age < 18 %}
        <p>小明同学</p>
    {% else %}
        <p>大明同学</p>
    {% endif %}

    <p>for循环</p>
    <ul>
        {% for student in student_list %}
            {% if loop.last %}
            <li style="background-color:#000;color: brown;">{{ student }}</li>
            {% else %}
            <li>{{ student }}</li>
            {% endif %}
        {% endfor %}
    </ul>

    <table border="1" align="center" width="680px">
        <tr>
            <td>序号</td>
            <td>ID</td>
            <td>名称</td>
            <td>价格</td>
            <td>库存</td>
        </tr>
        {# flask的注释 #}
        {# loop是jinja2模板引擎提供给开发者获取循环中的信息对象 #}
        {# loop.index 显示本次循环的次数,从1开始 #}
        {# loop.index0 显示本次循环的次数,从0开始 #}
        {# loop.first 显示本次是否属于循环的第一次,是则为真 #}

        {% for goods in goods_list %}
            {% if loop.index % 2 %}
            <tr bgcolor="#6495ed">{% else %}</tr>
            {% endif %}
                <td>{{ loop.index0 }}</td>
                <td>{{ goods.id }}</td>
                <td>{{ goods.name }}</td>
                <td>{{ goods.price }}</td>
                <td>{{ goods.num }}</td>
            {% endfor %}
    </table>

</body>
</html>

如图:

以上包括流程控制
主要包含两个:

- if/elif /else / endif
- for / endfor

在一个 for 循环块中你可以访问这些特殊的变量:

变量描述
loop.index当前循环迭代的次数(从 1 开始)
loop.index0当前循环迭代的次数(从 0 开始)
loop.revindex到循环结束需要迭代的次数(从 1 开始)
loop.revindex0到循环结束需要迭代的次数(从 0 开始)
loop.first如果是第一次迭代,为 True 。
loop.last如果是最后一次迭代,为 True 。
loop.length序列中的项目数。
loop.cycle在一串序列间期取值的辅助函数。

3.模板中特有的变量和函数

config、request、session、g变量、url_for()

主程序:


app.config['SECRET_KEY'] = '123sd'

@app.route('/')
def index():
    data = {}
    session['name'] = 'xiaohuihui'
    return render_template('index3.html', **data)


if __name__ == '__main__':
    app.run(debug=True)

模板 templates/index3.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {# 获取上下文对象 #}
    <p>{{ request.url }}</p>
    <p>{{ request.method }}</p>

    <p>{{ session }}</p>
    <p>{{ session.name}}</p>

    <p>{{ config.DEBUG }}</p>
    <p>{{ url_for('index') }}</p>

</body>
</html>

pycharm中设置当前项目的模板语言:
files/settings/languages & frameworks/python template languages。
设置下拉框为jinja2,保存

二、过滤器

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

在 jinja2 中,过滤器是可以支持链式调用的,示例如下

{{ "hello world" | reverse | upper }}

1.常见的内建过滤器

(1)字符串操作

safe:禁用转义
capitalize:把变量值的首字母转成大写,其余字母转小写
lower:把值转成小写
upper:把值转成大写
title:把值中的每个单词的首字母都转成大写
reverse:字符串反转
format:格式化输出
striptags:渲染之前把值中所有的HTML标签都删掉
    如果内容中,存在大小于号的情况,则不要使用这个过滤器,容易误删内容。
truncate: 字符串截断

(2)列表操作

first:取第一个元素
last:取最后一个元素
length:获取列表长度
sum:列表求和
sort:列表排序

(3)语句块过滤
{% filter upper %}
    #一大堆文字#
{% endfilter %}

主函数:


from flask import Flask, render_template

app = Flask(__name__,   # 当前flask应用运行的模块
            static_folder='static',  # 当前flask应用保存静态资源[css/js/img/音视频]
            static_url_path='/lib',  # 当前flask应用提供给外界访问的路径前缀,必须以/开头
            template_folder='templates'
        )

app.config['SECRET_KEY'] = '12sdf'

@app.route('/')
def index():
    data = {}
    data['message'] = 'hello,python,after 7 day,byebye'
    data['image'] = "<img src='/lib/images/1.jpg'>"
    return render_template('index4.html', **data)


if __name__ == '__main__':
    app.run(debug=True)

index4.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        img{
            width: 100px;
        }
    </style>
</head>
    <p>{{ message | upper }}</p>
    <p>{{ image | safe }}</p>
    <p>{{ message | reverse | upper }}</p>
    <p>{{ '<em>hello</em>' | striptags }}</p>
    <p>{{ '如果x<y,z>x,那么x和z之间是否相等?' | striptags }}</p>

    <p>{{ '床前明月光,疑是地上霜。' | truncate(5,False,'...',0) }}</p>

    <p>{{ [1,1,2,3,4,5,1,2,2,3,4] | unique | list }}</p>
<body>

</body>
</html>

2.自定义过滤器

过滤器的本质是函数。当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种实现方式:

  • 一种是通过Flask应用对象的 add_template_filter 方法
  • 通过装饰器来实现自定义过滤器

重要:自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器。

案例:给手机号码进行部分屏蔽
主函数:


from flask import Flask, render_template

app = Flask(__name__,
            static_folder='static',
            static_url_path='/lib',
            template_folder='templates'
        )

app.config['SECRET_KEY'] = '1ds2d'

# 自定义过滤器函数
def do_mobile(content):

    return content[:3]+'*****'+content[-3:]
app.add_template_filter(do_mobile, 'mobile')

@app.route('/')
def index():
    data = {}
    data['mobile_list'] = [
        '13564985647',
        '13564985648',
        '13564985649',
    ]
    return render_template('index5.html', **data)


if __name__ == '__main__':
    app.run(debug=True)

index5.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% for mobile in mobile_list %}
    <p>{{ mobile | mobile }}</p>
    {% endfor %}
</body>
</html>

三、模板继承

在模板中,可能会遇到以下情况:

  • 多个模板具有完全相同的顶部和底部内容
  • 多个模板中具有相同的模板代码内容,但是内容中部分值不一样
  • 多个模板中具有完全相同的 html 代码块内容

像遇到这种情况,可以使用 JinJa2 模板中的 继承 来进行实现

模板继承是为了重用模板中的公共内容。一般Web开发中,继承主要使用在网站的顶部菜单、底部。这些内容可以定义在父模板中,子模板直接继承,而不需要重复书写。

  • 标签定义的内容

      {% block top %} {% endblock %}
    
  • 相当于在父模板中挖个坑,当子模板继承父模板时,可以进行填充。

  • 子模板使用 extends 指令声明这个模板继承自哪个模板

  • 父模板中定义的块在子模板中被重新定义,在子模板中调用父模板的内容可以使用super()

父模板代码:base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}父级模板的内容{% endblock %}</title>
    {% block hander %}{% endblock hander %}
</head>
<body>
    {% block content %}
        <p>父级模板的content</p>
    {% endblock content %}
</body>
</html>

子模板代码:index6.html

{% extends 'base.html' %}
{% block title %}来自子模板的标题{% endblock title %}
{% block hander %}
    <script>
        alert(1)
    </script>
{% endblock hander %}

{% block content %}
    {{ super() }}
    <p>子模板的内容</p>
    {{ super() }}
{% endblock %}

from flask import Flask, render_template

app = Flask(__name__, template_folder='templates')

@app.route('/')
def index():
    data = {}
    return render_template('index6.html', **data)


if __name__ == '__main__':
    app.run(debug=True)

模板继承使用时注意点:

1. 不支持多继承

2. 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。

3. 不能在一个模板文件中定义多个相同名字的block标签。

4. 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。

四、解决csrf攻击

pip install flask_wtf

1.设置应用程序的 secret_key,用于加密生成的 csrf_token 的值

# 1. session加密的时候已经配置过了.如果没有在配置项中设置,则如下:
app.secret_key = "#此处可以写随机字符串#"

# 2. 也可以写在配置类中。
class Config(object):
    DEBUG = True
    SECRET_KEY = "dsad32"
    
"""加载配置"""
app.config.from_object(Config)

2.导入 flask_wtf.csrf 中的 CSRFProtect 类,进行初始化,并在初始化的时候关联 app

from flask.ext.wtf import CSRFProtect
CSRFProtect(app)

在表单中使用 CSRF 令牌:

<form method="post" action="/">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>

视图代码:

rom flask import Flask, render_template, request
from flask_wtf import CSRFProtect
app = Flask(__name__, template_folder='templates')

csrf = CSRFProtect(app)

app.config['SECRET_KEY'] = '254dgf'

@app.route('/')
def index():
    data = {}
    return render_template('index7.html', **data)

@app.route('/login', methods=['POST'])
def login():
    print(request.form)
    return 'ok'


if __name__ == '__main__':
    app.run(debug=True)

模板代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <form action="{{ url_for('login') }}" method="post">
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
        帐号:<input type="text" name="username" value=""><br><br>
        密码:<input type="password" name="password" value=""><br><br>
        <input type="submit" value="登录">
    </form>

</body>
</html>

五、数据库操作

1.ORM

ORM 全拼Object-Relation Mapping,中文意为 对象-关系映射。主要实现模型对象到关系数据库数据的映射
优点 :

  • 只需要面向对象编程, 不需要面向数据库编写代码.
    • 对数据库的操作都转化成对类属性和方法的操作.
    • 不用编写各种数据库的sql语句.
  • 实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
    • 不再需要关注当前项目使用的是哪种数据库。
    • 通过简单的配置就可以轻松更换数据库, 而不需要修改代码.

缺点 :

  • 相比较直接使用SQL语句操作数据库,有性能损失.
  • 根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.

2.Flask-SQLAlchemy

flask默认提供模型操作,但是并没有提供ORM,所以一般开发的时候我们会采用flask-SQLAlchemy模块来实现ORM操作。

SQLAlchemy是一个关系型数据库框架,它提供了高层的 ORM 和底层的原生数据库的操作。flask-sqlalchemy 是一个简化了 SQLAlchemy 操作的flask扩展。
SQLAlchemy: https://www.sqlalchemy.org/
中文文档: https://www.osgeo.cn/sqlalchemy/index.html

安装 flask-sqlalchemy【清华源】

pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple

如果连接的是 mysql 数据库,需要安装 mysqldb 驱动

pip install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple

安装flask-mysqldb时,注意

安装 flask-mysqldb的时候,python底层依赖于一个底层的模块 mysql-client模块
如果没有这个模块,则会报错如下:

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-21hysnd4/mysqlclient/

解决方案:

sudo apt-get install libmysqlclient-dev python3-dev

运行上面的安装命令如果再次报错如下:
   dpkg 被中断,您必须手工运行 ‘sudo dpkg --configure -a’ 解决此问题。

则根据提示执行命令以下命令,再次安装mysqlclient
	sudo dpkg --configure -a
	apt-get install libmysqlclient-dev python3-dev

解决了mysqlclient问题以后,重新安装 flask-mysqldb即可。
pip install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple
(1)数据库连接设置
class Config():
    DEBUG = True
    # 数据库连接配置
    # SQLALCHEMY_DATABASE_URI = "mysql://账号:密码@IP/数据库名?编码"
    SQLALCHEMY_DATABASE_URI = "mysql://root:123@127.0.0.1:3306/students?charset=utf8mb4"
    # 动态追踪修改设置,如未设置只会提示警告
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    # 查询时会显示原始SQL语句
    SQLALCHEMY_ECHO = True

app.config.from_object(Config)

配置完成需要去 MySQL 中创建项目所使用的数据库

$ mysql -uroot -p1
mysql > create database students charset=utf8mb4;
(2)常用的SQLAlchemy字段类型
模型字段类型名python中数据类型说明
Integerint普通整数,一般是32位
SmallIntegerint取值范围小的整数,一般是16位
BigIntegerint或long不限制精度的整数
Floatfloat浮点数
Numericdecimal.Decimal普通数值,一般是32位
Stringstr变长字符串
Textstr变长字符串,对较长或不限长度的字符串做了优化
Unicodeunicode变长Unicode字符串
UnicodeTextunicode变长Unicode字符串,对较长或不限长度的字符串做了优化
Booleanbool布尔值
Datedatetime.date日期
Timedatetime.time时间
DateTimedatetime.datetime日期和时间
LargeBinarystr二进制文件内容
(3)常用的SQLAlchemy列约束选项
选项名说明
primary_key如果为True,代表表的主键
unique如果为True,代表这列不允许出现重复的值
index如果为True,为这列创建索引,提高查询效率
nullable如果为True,允许有空值,如果为False,不允许有空值
default为这列定义默认值

3.数据库基本操作

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

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

class Config():
    DEBUG = True
    # 数据库连接配置
    # SQLALCHEMY_DATABASE_URI = "mysql://账号:密码@IP/数据库名?编码"
    SQLALCHEMY_DATABASE_URI = 'mysql://root:1@127.0.0.1:3306/students?charset=utf8mb4'
    # # 动态追踪修改设置,如未设置只会提示警告
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    # 查询时会显示原始SQL语句
    SQLALCHEMY_ECHO = True

app.config.from_object(Config)

db = SQLAlchemy()
db.init_app(app)

"""创建模型类"""
class Student(db.Model):
    __tablename__ = 'tb_student'
    id = db.Column(db.Integer, primary_key=True, comment='主键ID')
    name = db.Column(db.String(250), comment='姓名')
    age = db.Column(db.Integer, comment='年龄')
    sex = db.Column(db.Boolean, default=False, comment='性别')
    money = db.Column(db.DECIMAL(8, 2), nullable=True, comment='钱包')

    def __repr__(self):
        return self.name

class Teacher(db.Model):
    __tablename__ = 'tb_teacher'
    id = db.Column(db.Integer, primary_key=True, comment='主键ID')
    name = db.Column(db.String(250), comment='姓名')
    sex = db.Column(db.Boolean, default=False, comment='性别')
    option = db.Column(db.Enum('讲师', '助教', '班主任'), default='讲师', comment='教职')

    def __repr__(self):
        return self.name

class Course(db.Model):
    __tablename__ = 'tb_course'
    id = db.Column(db.Integer, primary_key=True, comment='主键ID')
    name = db.Column(db.String(250), unique=True, comment='课程名称')
    price = db.Column(db.Numeric(6, 2))

    def __repr__(self):
        return self.name

@app.route('/')
def index():
    return 'ok'

if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 根据模型创建所有的数据表
        db.drop_all()  # 删除模型对应的所有数据表
    app.run()

六、数据表操作

增删改查


from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

class Config():
    DEBUG = True
    # 数据库连接配置
    # SQLALCHEMY_DATABASE_URI = "mysql://账号:密码@IP/数据库名?编码"
    SQLALCHEMY_DATABASE_URI = 'mysql://root:1@127.0.0.1:3306/students?charset=utf8mb4'
    # # 动态追踪修改设置,如未设置只会提示警告
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    # 查询时会显示原始SQL语句
    SQLALCHEMY_ECHO = True

app.config.from_object(Config)

db = SQLAlchemy()
db.init_app(app)

"""创建模型类"""
class Student(db.Model):
    __tablename__ = 'tb_student'
    id = db.Column(db.Integer, primary_key=True, comment='主键ID')
    name = db.Column(db.String(250), comment='姓名')
    age = db.Column(db.Integer, comment='年龄')
    sex = db.Column(db.Boolean, default=False, comment='性别')
    money = db.Column(db.DECIMAL(8, 2), nullable=True, comment='钱包')

    def __repr__(self):
        return self.name

class Teacher(db.Model):
    __tablename__ = 'tb_teacher'
    id = db.Column(db.Integer, primary_key=True, comment='主键ID')
    name = db.Column(db.String(250), comment='姓名')
    sex = db.Column(db.Boolean, default=False, comment='性别')
    option = db.Column(db.Enum('讲师', '助教', '班主任'), default='讲师', comment='教职')

    def __repr__(self):
        return self.name

class Course(db.Model):
    __tablename__ = 'tb_course'
    id = db.Column(db.Integer, primary_key=True, comment='主键ID')
    name = db.Column(db.String(250), unique=True, comment='课程名称')
    price = db.Column(db.Numeric(6, 2))

    def __repr__(self):
        return self.name

@app.route('/')
def index():
    """数据库基本操作"""

    """添加数据"""
    # 添加一条数据
    # student = Student(name='xiaohong', age=16, money=100, sex=True)
    # db.session.add(student)
    # db.session.commit()

    # 批量添加多条数据
    data_list = [
        Student(name='xiaohui1号', age=16, money=1000, sex=True),
        Student(name='xiaohui2号', age=16, money=1000, sex=True),
        Student(name='xiaohui3号', age=16, money=1000, sex=True),
        Student(name='xiaohui4号', age=16, money=1000, sex=True),
        Student(name='xiaohui5号', age=16, money=1000, sex=True),
        Student(name='xiaohui6号', age=16, money=1000, sex=True),
    ]
    db.session.add_all(data_list)
    db.session.commit()

    """查询数据"""
    # 根据主键ID查询一条数据,如果ID不存在,则返回None不会报错!
    # student = Student.query.get(100)
    # if student is None:
    #     print('当前学生不存在!')
    # else:
    #     print(student)
    #     print(student.name, student.age)  # 获取属性

    # 根据查询条件获取一条数据
    # 模型.query.filter(模型.字段==条件值).first()
    # student = Student.query.filter(Student.id==1).first()
    # print(student)
    # print(student.name, student.money)

    # 根据查询条件获取多条数据
    # 模型.query.filter(模型.字段==条件值).all()
    # student_list = Student.query.filter(Student.id < 5).all()
    # print(student_list)
    # """
    # [xiaohong, xiaohui1号, xiaohui2号, xiaohui3号]
    # """
    # for student in student_list:
    #     print(student.name, student.money)

    """更新数据"""
    # 先查询后修改
    # student = Student.query.filter(Student.name=='xiaohong').first()
    # student.money += 1000
    # db.session.commit()

    # 直接根据条件修改
    # Student.query.filter(Student.name=='xiaohong', Student.money==2100).update({Student.money:3000})  # 乐观锁
    # 实现类似django的F函数效果,字段值累加
    # Student.query.filter(Student.name=='xiaohong').update({Student.money:Student.money+500})
    # db.session.commit()

    """删除数据"""
    # 先查询后删除
    # student = Student.query.filter(Student.name=='xiaohui6号').first()
    # db.session.delete(student)
    # db.session.commit()

    # 直接根据条件进行删除操作
    Student.query.filter(Student.name=='xiaohui5号').delete()
    db.session.commit()

    return 'ok'


if __name__ == '__main__':
    app.run()

1.数据基本查询

常用的SQLAlchemy查询过滤器

过滤器说明
filter()把过滤器添加到原查询上,返回一个新查询
filter_by()把等值过滤器添加到原查询上,返回一个新查询
limit()使用指定的值限定原查询返回的结果
offset()偏移原查询返回的结果,返回一个新查询
order_by()根据指定条件对原查询结果进行排序,返回一个新查询
group_by()根据指定条件对原查询结果进行分组,返回一个新查询

常用的SQLAlchemy查询结果的方法

方法说明
all()以列表形式返回查询的所有结果
first()返回查询的第一个结果,如果未查到,返回None
first_or_404()返回查询的第一个结果,如果未查到,返回404
get()返回指定主键对应的行,如不存在,返回None
get_or_404()返回指定主键对应的行,如不存在,返回404
count()返回查询结果的数量
paginate()返回一个Paginate分页器对象,它包含指定范围内的结果
having返回结果中符合条件的数据,必须跟在group by后面,其他地方无法使用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值