IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Flask 框架学习1 -> 正文阅读

[Python知识库]Flask 框架学习1

常用快捷键:

????????自动导包:option+enter(mac)ctl+enter(windows)

? ? ? ? 查看传参:ctr+ p

? ? ? ? 新增文件:ctr + n

1、hello_world

from flask import Flask


# 创建应用对象
# __name__:如果程序直接在当前文件执行,值为__main__,如果从其他文件调用执行,表示模块名称
# static_url_path:静态资源路径默认为:./static
#template_folder: 模板路径,默认为:./templates
app = Flask(__name__)

# 使用路由路径,绑定视图函数
@app.route('/')
def hello_world():
    return 'hello world!'

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

这是flask框架最简单的一段代码,以及其中参数的含义

1、如果一个路由装饰多个函数,那么访问的是哪个函数?

????????访问先被装饰的函数,相当于一个队列,先进先出

2、如果一个视图函数由多个路由装饰,那么优先访问哪个路径?

????????所有的路径都能访问视图函数

2、methods

若一个路由装饰多个函数,可以通过methods,确认请求方式来确认访问的视图函数.methods 是一个列表,不同请求方式使用逗号分割

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world!'

@app.route('/', methods=["post"])
def hello_world2():
    return 'hello world2!'

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

3、url_for

url_for 是属于app的方法,在flask模块中

格式:url_for('试图函数名字', key=value)

可以通过视图函数找到对应的路由路径,用于服务器内部资源定位,常与redirect连用

使用url_for传递参数时,接受的参数名需要与传递的参数名一致

from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world<a href={}>点击按钮</a>'.format(url_for('hello_world2'))

@app.route('/index')
def hello_world2():
    return 'hello world2!'

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

传参:

from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world<a href={}>点击按钮</a>'.format(url_for('hello_world2', money=100))

@app.route('/index/<int:money>')
def hello_world2(money):
    return 'hello world2!,钱数:{}'.format(money)

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

4、redirect

重定向,可以通过路由找到视图函数,并自动跳转执行

格式:redirect('路径'),常与url_for一起使用

from flask import Flask, url_for, redirect

app = Flask(__name__)

@app.route('/')
def hello_world():
    return redirect(url_for('hello_world2', money=100))

@app.route('/index/<int:money>')
def hello_world2(money):
    return 'hello world2!,钱数:{}'.format(money)

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

5、返回json数据

有两种方式:

a:通过jsonify(dict),flask模块中

b:json.dump() ,需要配合response对象设置,不推荐

from flask import Flask, url_for, redirect, jsonify

app = Flask(__name__)

@app.route('/')
def hello_world():
    dict={
        "name":"zhangsan",
        "age":19
    }

    return jsonify(dict)

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

在浏览器控制台可以看到响应头的conten-type是json格式

使用json.dumps()

from flask import Flask, url_for, redirect, jsonify, json, make_response

app = Flask(__name__)

@app.route('/')
def hello_world():
    dict={
        "name":"zhangsan",
        "age":19
    }

    return json.dumps(dict)

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

上面代码在浏览器返回的是text格式,若要返回json格式,还需要借助response对象

6、路由传参

格式:app.route("路径/<数据类型:变量名>")

数据类型:

? ? ? ? int:整数

? ? ? ? float:小数

? ? ? ? path:字符串

from flask import Flask, url_for, redirect, jsonify

app = Flask(__name__)

@app.route('/<path:reasion>')
def hello_world(reasion):

    return "我今天是因为{}迟到了!".format(reasion)


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

但是没办法限制传参的个数,可以通过自定义转换器

之所以可以编写int、float、path是因为系统已经添加默认的转换器,如果要限制参数的具体个数等类型需要自定义

a、自定义类,继承自BaseConverter

b、重写__init__方法,接受两个参数,调用父类__init__方法初始化父类内容

c、将规则赋值到子类对象

d、将转换器添加到系统默认的转换器列表中

查看系统自带的转换器:app.url_map.converters

from flask import Flask, url_for, redirect, jsonify
from werkzeug.routing import BaseConverter

app = Flask(__name__)


class MyConvert(BaseConverter):
    def __init__(self, url_map, regex):
        super(MyConvert, self).__init__(url_map)
        self.regex = regex


app.url_map.converters['re'] = MyConvert


@app.route('/<re("1[35768]\d{9}"):number>')
def hello_world(number):

    return "the phonenumber is {}".format(number)


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

?to_python 方法

from flask import Flask, url_for, redirect, jsonify
from werkzeug.routing import BaseConverter

app = Flask(__name__)


class MyConvert(BaseConverter):
    def __init__(self, url_map, regex):
        super(MyConvert, self).__init__(url_map)
        self.regex = regex

    # 重写to_python 方法
    def to_python(self, value):
        return 'xixi' + value


app.url_map.converters['re'] = MyConvert


@app.route('/<re("1[35768]\d{9}"):number>')
def hello_world(number):

    return "the phonenumber is {}".format(number)


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

请求结果

在匹配完规则后,进入到视图函数之前执行该方法,可以过滤数据或编码操作

7、调试模式

在运行程序的时候,可以通过app.run(debug=True)进入调试模式,修改代码之后,保存,自动重新启动

好处:

? ? ? ? a、程序改动之后,不需要重新启动既可以部署

? ? ? ? b、如果程序报错,有友好提示界面? ? ? ??


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

8、abort

主动停止程序,会配合@app.errorhandler使用,用来自定义错误界面

from flask import Flask, abort

app = Flask(__name__)

@app.route('/')
def hello_world():
    abort(403)
    return "hello world!!"

常与@app.errorhandler装饰器使用,可以自定义错误

from flask import Flask, abort

app = Flask(__name__)

@app.route('/')
def hello_world():
    abort(404)
    return "hello world!!"


@app.errorhandler(404)
def exception_404(e):
    return "找不到资源"


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

##########################################################
from flask import Flask, abort

app = Flask(__name__)

@app.route('/')
def hello_world():
    # abort(404)
    raise(Exception("big error"))

    return "hello world!!"


@app.errorhandler(404)
def exception_404(e):
    return "找不到资源"

@app.errorhandler(Exception)
def exception(e):
    return "出现大错误"


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

9、请求对象和返回对象

request:和请求对象相关,里面封装了请求有关的信息,比如请求方式、请求路径、请求参数

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    print(request.method)
    print(request.url)
    print(request.args)
    return "hello world!"

if __name__ == '__main__':

    app.run(debug=True)

###################################
# 响应:
# 127.0.0.1 - - [02/May/2022 13:26:02] "GET
# http://127.0.0.1:5000/?name=zhagnsan&age=13
# ImmutableMultiDict([('name', 'zhagnsan'), ('age', '13')])
# GET /?name=zhagnsan&age=13 HTTP/1.1" 200 -

响应对象,在后端返回数据的时候,有两种主要方式

直接返回

? ? ? ? 1、响应体? ? ? ? return “hello world”

? ? ? ? 2、响应体+状态码? ? ? ? return? “hello world”,666

? ? ? ? 3、响应体+状态码+响应头????????return? “hello world”,666,{"Content-Type":"application/json"}

手动封装response对象返回

response = make_response(响应体)

response.status = "666"

response.hearder["Content-Type"] =?"application/json"

10、请求勾子

在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:

  • 在请求开始时,建立数据库连接;
  • 在请求开始时,根据需求进行权限校验;
  • 在请求结束时,指定数据的交互格式;

请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子

before_first_request:在处理第一个请求前执行

before_request:每次请求前执行,如果在某修饰的函数中返回了一个响应,视图函数将不再被调用

after_request:如果没有抛出错误,在每次请求后执行;接受一个参数:视图函数作出的响应;在此函数中可以对响应值在返回之前做最后一步修改处理;需要将参数中的响应在此参数中进行返回

teardown_request:每次请求后执行,接受一个参数:错误信息,如果有相关错误抛出

11、cookie和session

http 是一种无状态协议,浏览器请求服务器是无状态的,有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等

  • 在客户端存储信息使用Cookie
  • 在服务器端存储信息使用Session

设置cookie:当前浏览器访问服务器时,由服务器设置一些状态信息到浏览器中,存储在浏览器中

? ? ? ? response.set_cookie(key,value,max_age)? ? ? ? max_age: 过期时间

获取cookie:

? ? ? ? request.cookies.get(key)

from flask import Flask, make_response, request

app = Flask(__name__)

@app.route('/set_cookie')
def set_cookie():
    response = make_response()
    response.set_cookie('name','zhangsan')
    response.set_cookie('age',"13", 10)
    return response

@app.route('/get_cookie')
def get_cookie():
    name = request.cookies.get('name')
    age = request.cookies.get('age')
    return "name is {}, age is {}".format(name, age)

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

设置cookie

获取cookie

session: 当浏览器访问服务器的时候,由服务器创建并存储在服务器内部,依赖于cookie

? ? ? ? 一般用来存储用户的隐私数据,比如:密码信息,登录信息,银行卡信息等

seesion数据设置过程:

? ? ? ? 1、当第一次请求的时候,在服务器端会给客户端设置响应的session数据,返回给客户端,存储在cookie中

? ? ? ? 2、当第二次发送请求是,cookie中会携带sessionID到服务器,通过ID可以获取到session中的数据

? ? ? ? 每一个用户向服务器请求的时候都会给其开辟对应的空间保存session数据

设置session:

? ? ? ? session[key] = value?

? ? ? ? 设置session的编号生成依赖于SECRE_KEY

获取session:

? ? ? ? session.get(key)? 若为空,直接返回空,推荐

? ? ? ? session[key]? ? ? ? 若为空,报错。不推荐

from flask import Flask, session

app = Flask(__name__)
app.config['SECRET_KEY'] = 'jhfjafjkd'

@app.route('/set_session/<name>')
def set_session(name):
    session['name'] = name
    return '设置session成功'

@app.route('/get_session')
def get_session():
    se = session.get('name')
    return 'session is {}'.format(se)

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

?12、flask_script 动态指定IP和端口

在时机开发中,项目封板之后,如果部署的服务器发生变化,意味着IP和端口可能出现变化,如果直接修改源代码风险比较大,而且繁琐,可以通过flask_script解决,可以动态指定运行的IP和端口

安装:

pip install flask-script

创建Manager对象,关联app应用程序对象

运行:python xxx.py runserver -h 127.0.0.1 -p 8888

from flask import Flask
from flask_script import Manager

app = Flask(__name__)
# 设置调试模式
app.config["DEBUG"] = True

# 创建manager管理对象,关联app应用程序对象
manager = Manager(app)


@app.route('/')
def hello_world():
    return "hello world"

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

13、模板渲染

Flask中页面的渲染是通过jinja2模块来实现的,依赖于render_template函数

模板中的注释:{# #}

我们在编写模板时,变量都是没有提示的,设置步骤:

使用格式:

? ? ? ? return render_temperate('模板文件',key=value)

? ? ? ? 将HTML文件渲染撑响应体对象,可以携带value值到页面中

模板的默认位置:templates,若没有该文件,报错

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def hello_world():
    return render_template('file01.html')

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

模板中的常见语法? ? ? ??

? ? ? ? 获取变量:{{变量名称}}

? ? ? ? 分支语句:{% if 条件A%}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 语句1

? ? ? ? ? ? ? ? ? ? ? ? ? ?{%elif 条件B%}

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 语句2

? ? ? ? ? ? ? ? ? ? ? ? ? ?{%endif%}

? ? ? ? 循环语句:

? ? ? ? ? ? ? ? {%for 变量 in 容器%}

? ? ? ? ? ? ? ? ? ? ? ? 语句

? ? ? ? ? ? ? ? ?{%endfor%}

在HTML文件中若元祖或者列表取值时,可以使用list.0或者list[0],若是字典,可以dict.key

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def hello_world():
    num = 3
    str = '你好'
    tuple = (10, 11, 12, 13)
    list = [1, 2, 3, 4]
    dict = {
        "name":"张三",
        "age":17
    }
    return render_template('file01.html', num=num, str=str, tuple= tuple, list=list, dict=dict)

if __name__ == '__main__':
    app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>this is a template</h1>
    <h2>整数:{{ num }}</h2>
    <h2>字符串:{{ str }}</h2>
    <h2>元祖:{{ tuple }}, 分开获取:{{ tuple.0 }}, {{ tuple[2] }}</h2>
    <h2>列表:{{ list }}, 分开获取: {{ list.0 }}, {{ list[1] }}</h2>
    <h2>字典:{{ dict }}, 分开获取: {{ dict.name }}, {{ dict.age }}</h2>

    <h2>遍历列表中的偶数</h2>
    {% for n in list %}
        {% if n %2==0 %}
            <h3>{{ n }}</h3>
        {% endif %}
    {% endfor %}
    <h2>获取元祖的编号</h2>
    {% for num in tuple %}
{#        <h3>索引:{{ loop.index0 }}, 值是:{{ num }}</h3> index0 表示从0开始,若是index,表示从1开始#}
        <h3>索引:{{ loop.index0 }}, 值是:{{ num }}</h3>
    {% endfor %}
    <h2>遍历字典</h2>
    {% for key in dict %}
{#        <h3>{{ key }} = {{ dict[key] }}</h3>  不能通过dict.key来取值,这表示dict中有个主键是key,此时key不是一个变量#}
        <h3>{{ key }} = {{ dict[key] }}</h3>
    {% endfor %}
</body>
</html>

过滤器

常见的过滤器有两种:

字符串过滤器:

upper:将字符串转成大写

lower:将字符串转成小写

reverse:将字符串反转

2、列表过滤器

first:第一个元素

last:最后一个元素

sum:取和

sort:排序

使用方法:变量名|过滤器

14、模板复用

宏:提前定义好模板代码块需要的时候调用即可

定义:{ %? macro 宏名(参数)? ?% }

? ? ? ? ??{ %? endmacro? ?% }

{% macro input(name,value='',type='text') %}
    <input type="{{type}}" name="{{name}}"
        value="{{value}}" class="form-control">
{% endmacro %}

使用:

? ? ? ? 当前文件:{{宏名(参数)}}

? ? ? ? 其他文件:{ %import ”宏所在的文件“ as 别名% }

? ? ? ? ? ? ? ? ? ? ? ? ? {% 别名.宏名(参数)?%}

模板继承是为了重用模板中的公共内容,共性抽取,代码复用,继承之后可以扩展子模板独有的内容

{%extends "文件名"%}

包含:A完全用友B内容,一般对于不需要改变的内容使用包含

{%include??"文件名" ignore missing%}? ? ? ? #ignore missing如果文件不存在,不报错

模块的定义:

{%block 名称%}

{%endblock%}

继承

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% extends 'file03fu.html' %}


</body>
</html>

15、flask表单

传统表单:有大量的HTML定义好的标签组成

缺点:一旦表单编写完成,如果需要增加额外的功能,就不能实现

传统表单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/register" method="post">

    <label>用户名</label><input type="text" name="username" placeholder="请输入用户名"><br>
    <label>密码</label><input type="text" name="password" placeholder="请输入密码"><br>
    <label>确认密码</label><input type="text" name="repassword" placeholder="请输入确认密码"><br>
    <input type="submit" value="提交">

</form>

</body>
</html>
from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    return render_template('file04nom.html')


@app.route('/register', methods=["post"])
def register():
    print(request.form)
    usrname  =request.form.get('username')
    password  =request.form.get('password')
    repassword  =request.form.get('repassword')
    if not all([usrname, password, repassword]):
        return '没有填写必要内容'
    if password != repassword:
        return "密码不一致"
    return '注册成功'

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

Flask_WTF:通过类的方式渲染页面,包含字段和验证函数

步骤:

  • 安装,导包
  • 自定义类,继承自FlaskForm
  • 编写字段,验证函数
  • 创建表单对象
  • 渲染到页面中

包含csrf验证机制

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

app = Flask(__name__)
app.config["SECRET_KEY"] = 'yhfjnfhhf'

# 自定义类,继承自FlaskForm
class MyForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired()])
    password = PasswordField('密码', validators=[DataRequired()])
    repassword = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password', '两次输入的密码必须一致!')])
    submit = SubmitField('提交')

@app.route('/')
def hello_world():
    # 创建表单
    form = MyForm()

    return render_template('file05wtf.html', form=form) #将form对象传递到模板文件中

@app.route('/register', methods=["post"])
def register():
    # 根据创建的内容创建表单
    form = MyForm()
    # 验证提交的内容
    if form.validate_on_submit():
        return "注册成功"
    return "注册失败"

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

HTML文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/register" method="post">

    {{ form.csrf_token }}

    {{ form.username.label }}
    {{ form.username }}<br>

    {{ form.password.label }}
    {{ form.password }}<br>

    {{ form.repassword.label }}
    {{ form.repassword }}<br>

    {{ form.submit }}

</form>
</body>
</html>

16、数据库

常用的数据库命令:

# 进入mysql,回车输入密码
mysql -uroot -p

# 退出登录
quit
exit
ctrl+d
# 查看所有数据库
show databases;
# 使用数据库
use 数据库名;
# 删除数据库
drop 数据库名;
# 查看当前数据库中的所有表
show tables;
# 删除表
drop table 表名;
# 数据库备份
mysqldump -uroot -p 数据库名 > python.sql
# 数据库恢复
mysql -uroot -p 数据库名 < python.sql

flask操作数据库是通过库战报Flask_Sqlalchemy

操作流程:

  • 安装,导入? ? ? ?

? ? ? ? ? ? ? ? pip install flask-sqlalchemy

????????????????pip install flask-mysqldb? ?若报错可以安装pip install pymsql

  • 设置数据库的配置信息

? ? ? ? ? ? ? ? <协议mysql+pymsql>://<用户名>:<密码>@<IP地址>:<端口号>/<数据库名称>

? ? ? ? ? ? ? ? 如果安装的是mysqld,协议使用mysql;如果安装的是pymysql,协议使用mysql+pymysql

  • 创建ORM对象SQLALchemy,关联app
  • 定义模型类
  • 操作(方法)
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

# 设置数据库信息
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:123456@127.0.0.1:3306/pytest"
# 设置数据库的追踪数据变化,并压制警告信息
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

#创建SQLAlchemy对象
db = SQLAlchemy(app)
# 定义模型类 角色模型
class Role(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, nullable=False)
    # 外键
    role_id = db.Column(db.Integer, db.ForeignKey(Role.id))


@app.route('/')
def hello_world():
    return "hello world"

if __name__ == '__main__':
    db.create_all() # 将继承自db.Model全部新增
    #db.drop_all() 会将继承自db.Model的表全部删掉
    #db.session.add(obj) 添加数据,提交回话后才会插入到数据库
    #db.session.delete(obj) 删除数据,提交回话后才会更新数据库
    #db.session.commit() 提交会话
    #db.session.rollback() 回滚
    # 添加多条
      #us9 = User(name='li',email='li@163.com',password='4526342',role_id=ro2.id)
      #us10 = User(name='sun',email='sun@163.com',password='235523',role_id=ro2.id)
      #db.session.add_all([us9,us10]) 添加的是一个列表
      #db.session.commit()
    app.run(debug=True)

执行成功后,数据库会新增两个表,role表和name表,若没有指定表名称,默认是类名的小写,在类中设置__tablename__=="表名"即可

User.query.all()    #查询所有用户数据
User.query.count()    #查询有多少个用户
User.query.filter_by(name='wang').all() # 精确查询,通过name查询
User.query.first()    #查询第1个用户
#查询id为4的用户
User.query.filter_by(id=4).first()
User.query.get(4)
User.query.filter(id==4).first() # filter用于模糊查询
#查询名字结尾字符为g的所有数据[开始/包含]
User.query.filter(User.name.endswith('g')).all()
User.query.filter(User.name.startswith('g')).all() # 以g开头的
User.query.filter(User.name.contains('g')).all()    # 包含g
#查询名字不等于wang的所有数据
User.query.filter(User.name != 'wang').all()
#查询名字和邮箱都以 li 开头的所有数据
User.query.filter(User.name.startswith('li'),User.email.startswith('li'))
#查询password是 `123456` 或者 `email` 以 `itheima.com` 结尾的所有数据
from sqlalchemy import or_
User.query.filter(or_(User.password=='123456', User.email.endswith('itheima.com'))).all()

#查询id为 [1, 3, 5, 7, 9] 的用户列表
from sqlalchemy import in_
User.query.filter_by(User.id.in_([1, 3, 5, 7, 9])).all()
# 查询name为liu的角色数据
user = User.query.filter_by(name="liu").first()
role = Role.query.filter(Role.id == user.role_id).first()
# 查询所有用户数据,并以邮箱排序
User.query.order_by(User.email).all()    #默认升序
User.query.order_by(User.email.desc()).all()     #降序返回
#每页3个,查询第2页的数据
paginate = User.query.paginate(2, 3, False) # False 有错误不输出
paginate.pages    # 返回页数
paginate.items    # 显示第二页的所有数据


#查询数据后删除
user = User.query.first()
db.session.delete(user)
db.session.commit()
#更新数据
user = User.query.first()
user.name = 'dong'
db.session.commit()

17、backref 反向引用

数据库查询操作:

  1. 如果知道了用户对象,能不能快速查询出该用户所扮演的角色。例如:user.role
  2. 如果知道了角色对象,能不能快速查询出哪些用户扮演了该角色。例如:role.user

使用relationship关系属性,设置backref反向引用,一般建立在一方,外键在多方
一对多:A表中的一条数据对应B表中的一条数据,B表中的一条数据对应A表中的多条数据,此时A与B是多对一的关系

In [1]: from test_query import *

In [2]: user = User.query.filter(User.name=='liu').first()

In [3]: user.role
Out[3]: <role:1,admin>


In [2]: admin = Role.query.filter(Role.name=='admin').first()

In [3]: admin
Out[3]: <role:admin>

In [4]: admin.users
Out[4]: 
[<user:wang,wang@163.com,123456>,
 <user:zhou,zhou@163.com,456789>,
 <user:qian,qian@gmail.com,1543567>,
 <user:liu,liu@itheima.com,867322>]

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-05-06 11:01:43  更:2022-05-06 11:02:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 16:56:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码