小工具知识网

当前位置: 首页 > 行业知识 > Python-Flask 快学

行业知识

Python-Flask 快学

2026-11-12 09:59:26 来源:互联网转载

flask���Python的一个轻型Web框架.

使用pycharm自动创建项目,也可以手动创建,以下是目录的结构:

├── app.py
├── static
└── templates

一、创建一个简单应用

from flask import Flaskapp = Flask(__name__) @app.route('/')def hello_world():    return "hello world "if __name__ == '__main__':    app.run()

其中,创建Flask实例时,可以自定配置主要有:

参数说明
static_path静态文件访问路径(不推荐使用,使用 static_url_path 代替)
static_url_path指定静态文件的访问路径(默认为 / + static_folder)
static_folder指定存放静态文件资源的文件夹的名称(默认为static)
template_folder指定存放模板的文件夹的名称(默认为templates)

二、路由规则

1.简单路由

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

2.带参数的路由

2.1不限定类型

@app.route("/user/")def user_info(username):    return "hello %s" % username

2.2限定类型

@app.route("/user/")def user_info(username):    return "hello %s" % username

注:这里是string而不是str

其他的类型有: int 、 float、uuid、path

3.正则路由

在Flask中是不能直接使用re的,需要使用转换器。转换器的作用就是:过滤指定用户。

使用正则路由的步骤:

1、导入转换器基类(BaseConverter)

2、自定义转换器(需要继承BaseConverter)

3、把自定义的转换器添加到转换器字典中

4、在路由中使用转换器

from flask import Flask, render_template# 第一步from werkzeug.routing import BaseConverterapp = Flask(__name__)  # 第二步class RegexConverter(BaseConverter):    def __init__(self, url_map, *args):        super(RegexConverter, self).__init__(url_map)        # 正则参数        self.regex = args[0]  # 第三步app.url_map.converters['re'] = RegexConverter  # 第四步@app.route("/user/")def user_info(username):    return "hello %s" % username  @app.route('/')def hello_world():    return render_template("index.html")  if __name__ == '__main__':    app.run() 

系统自带的转换器

DEFAULT_CONVERTERS = {

‘default’: UnicodeConverter,

‘path’: PathConverter,

‘string’: UnicodeConverter,

‘any’: AnyConverter,

‘int’: IntegerConverter,

‘float’: FloatConverter,

‘uuid’: UUIDConverter,

}

其实很多都是参数路由的

4.限定请求方式

加上一个methods参数限定请求的方式,注意methods应该是一个list

from flask import request  @app.route("/user", methods=["get", "post"])def user():    if request.method == "get":        return "user"    elif request.method == "post":        pass    else:        pass

注意request是需要从falsk中导入

三、响应规则

1.html

1.1 html文本

@app.route("/user")def user():    return "

User Info

"

1.2 html文件

from flask import render_template @app.route('/')def hello_world():    return render_template("index.html")

2.json

from flask import jsonify @app.route("/user")def user():    data = {        "user_name": "lczmx",        "age": "18"    }    return jsonify(data)

3.重定向

from flask import redirect @app.route("/index")def index():    return redirect("/")

4.视图跳转

from flask import redirectfrom flask import url_for  @app.route("/user/")def user(user_id):    if user_id > 200:        return redirect(url_for("vip_user", user_id=user_id))    else:        return redirect(url_for("general_user"))  @app.route("/vip_user/")def vip_user(user_id):    return "vip_user %s" % user_id  @app.route("/general_user")def general_user():    return "general_user"

5.状态码

@app.route('/')def index():    return render_template("index.html"), 200

200就是状态码,可以是其他的

四、模板引擎

注:Flask的模板引擎是jinja2, 与django的很相似

1.变量

使用: {{ 变量名 }}

app.py中传参

@app.route('/')def index():    return render_template("index.html", name="嘻嘻嘻")

2 注释

使用: {# 多行注释 #}

3 过滤器

使用: {{ var|filter }}

3.1 常用的过滤器

设置默认值: {{ data.bool|default(‘我是默认值’,boolean=True) }}

禁用转义:{{ 'hello' | safe }}

删除标签:{{ 'hello' | striptags }}

首字母大写:{{ ‘hello’ | capitalize }}

所有值小写:{{ ‘HELLO’ | lower }}

首字母大写:{{ ‘hello world’ | title }}

字符串反转:{{ ‘hello’ | reverse }}

字符串截断:{{ ‘hello world’ | truncate(5) }}

拼接成字符串: {{ [1,2,3,4] | join(‘’) }}

字符的格式化: {{ '我叫%s '|format(‘lczmx’) }}

获取长度:{{ [1,2,3,4,5,6] | length }}

列表求和:{{ [1,2,3,4,5,6] | sum }}

列表排序:>{{ [6,2,3,1,5,4] | sort }}

3.2 自定义过滤器

方法1: 通过Flask对象(app)的add_template_filter方法

def add_suffix(line):    return line + "--嘻嘻嘻" # 可以给过滤器器一个名字,如果没有,默认就是函数的名字app.add_template_filter(add_suffix,'add_suffix')

方法2: 使用装饰器来实现

# 使用装饰器事项过滤器,# 如果不传入参数,默认过滤器名字就是函数的名字@app.template_filter()def add_suffix(line):    return line + "--嘻嘻嘻"

4 标签

4.1 if

{% if user_info.nid == 10 %}    
  • {{ user_info.msg1 }}
  • {% elif user_info.nid == 20%}
  • {{ user_info.msg2 }}
  • {% else %}
  • {{ user_info.msg3 }}
  • {% endif %}

    4.2 for

    {% for name in name_list %}    
  • {{ name }}
  • {% endfor %}

    不能使用continue和break

    注:

    在for中有一个关键字叫loop,使用loop可以查看当前的迭代状态

    下面列出我认为有用的loop方法

    方法说明
    index0获取当前迭代的索引(从0开始)
    index获取当前迭代的索引(从1开始)
    first是否为第一次迭代
    last是否为最后一次迭代
    length要迭代的数据长度
    nextitem下一项
    previtem前一项
    {% for k,v in data.items() %}   
  • {{ k }}--{{ v }}
  • {{ loop.index }}
  • {{ loop.index0 }}
  • {{ loop.first }}
  • {{ loop.last }}
  • {{ loop.length }}
  • {{ loop.nextitem}}
  • {{ loop.previtem}}
  • {{ loop.changed}}
  • {{ loop.cycle}}
  • {{ loop.revindex}}
  • {{ loop.revindex0}}
  • {% endfor %}

    5.导入

    导入一个html文件,主要是导入一些可复用的.

    {% include "layout.html" %}

    6 继承

    比如我现在有一个模板base.html需要在index.html中继承.

            Title{% block title %}{% endblock %}    

    今天是个好日子

    {% block content%}

    我是内容

    {% endblock %}{% block js %}{% endblock %}

    用block留出填充部分

    {% extends "base.html" %}{% block title %}    

    啦啦啦

    {% endblock %}{% block js %}{% endblock %}

    在另外一个html中就可以继承修改一些东西了

    **注: block后面跟着名字

    五、获取请求数据

    注意: 需要先导入request: form flask import request

    常用的request属性有:

    属性名说明
    request.scheme获取请求协议
    request.method获取本次请求的请求方式(GET / POST)
    request.args获取以get请求方式提交的数据
    request.form获取以post请求方式提交的数据
    request.cookies获取cookies中的相关信息
    request.headers获取请求信息头的相关信息
    request.files获取上传的文件
    request.path获取请求的资源具体路径(不带参数)
    request.full_path获取完整的请求资源具体路径(带参数)
    request.url获取完整的请求地址,从协议开始
    request.files获取上传的文件用(save进行保存)

    注: arequest.args,request.form ,request.files 的返回值都是字典。

    六、会话控制

    1.cookie

    Cookie是由服务器端生成,发送给客户端浏览器,浏览器会将Cookie的key/value保存,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie的key/value可以由服务器端自己定义。

    Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用

    Cookie基于域名安全,不同域名的Cookie是不能互相访问的

    如访问huya.com时向浏览器中写了Cookie信息,使用同一浏览器访问 baidu.com时,无法访问到huya.com写的Cookie信息

    浏览器的同源策略针对cookie也有限制作用.

    当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器,所以在request中可以读取Cookie信息

    使用场景: 登录状态, 浏览历史, 网站足迹

    1.1 设置cookie

    from flask import make_response @app.route('/set_cookie')def set_cookie():    res = make_response('set cookie page')    res.set_cookie('username', 'lczmx', max_age=604800)  # max_age 是cookie有效期,单位为秒, 这里刚好设置一周时间    return res

    ​编辑

    1.2 获取cookie

    from flask import request @app.route('/vip')def resp_cookie():     user_name = request.cookies.get('username')     if user_name == "lczmx":         return "vip"     else:         return "bye"

    2.session

    对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息

    在服务器端进行状态保持的方案就是Session

    注意: Session依赖于Cookie,而且flask中使用session,需要配置SECRET_KEY选项,否则报错.

    2.1 配置SECRET_KEY

    生成SECRET_KEY:

    这里使用操作系统的密码随机生成器生成

    命令行输入:

    import os

    os.urandom(24)

    在config.py中:

    CSRF_ENABLED = TrueSECRET_KEY = 'SECRET_KEY粘贴在这里'

    在app.py中

    import config app.config.from_object(config)

    其实,所有的配置都应该放在config文件中,然后导入

    2.2 设置session

    from flask import session @app.route('/set_session')def set_session():     session['username'] = 'xxx'     session['password'] = '123456'     return 'success'

    一定要先配置SECRET_KEY

    2.3 获取session

    from flask import session, jsonify @app.route('/login')def login():     user_name = session.get('username')     pass_word = session.get('password')     if user_name == "xxx" and pass_word == "123456":         return jsonify({"status": 1, "msg": "success"})     else:         return jsonify({"status": 0, "msg": "failed"})

    七、Models

    假如使用过django的orm,我相信一般人都不会直接写sql语句操作数据库了.那么Flask有没有一款orm呢?应该说是有吧.该ORM是SQLAlchemy, 首次发行于2006年2月,并迅速地在Python社区中最广泛使用的ORM工具之一,不亚于Django的ORM框架。

    1 安装

    默认安装Flask是不带flask-sqlalchemy,需要手动安装

    pip install flask-sqlalchemy# 如果连接的是 mysql 数据库,需要安装 flask-mysqldbpip install flask-mysqldb# 提示:如果flask-mysqldb安装不上,安装, pip install pymysql 

    2 配置

    操作数据库需要先创建一个db对象,通常写在exts.py文件里。

    exts.py:

    from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()

    flask项目一般将数据库配置写入config.py文件里面,配置在创建引擎前需写好,不要在程序运行时修改配置,如下

    config.py:

    HOST = '127.0.0.1'PORT = '3306'   # 在mysql中使用show global variables like 'port';查看端口DATABASE = 'test'USERNAME = 'root'PASSWORD = '123456' DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(username=USERNAME,                                         password=PASSWORD, host=HOST,                                         port=PORT, db=DATABASE) SQLALCHEMY_DATABASE_URI = DB_URISQLALCHEMY_TRACK_MODIFICATIONS = FalseSQLALCHEMY_ECHO = True

    配置选项

    名称说明
    SQLALCHEMY_DATABASE_URI连接的数据库。示例:mysql://username:password@host/post/db?charset=utf-8
    SQLALCHEMY_BINDS一个将会绑定多种数据库的字典
    SQLALCHEMY_ECHO是否调试
    SQLALCHEMY_POOL_SIZE数据库池的大小,默认值为5
    SQLALCHEMY_POOL_TIMEOUT连接超时
    SQLALCHEMY_POOL_RECYCLE自动回收连接的秒数
    SQLALCHEMY_TRACK_MODIFICATIONS默认为True ,Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。(需要内存, 可以禁用)
    SQLALCHEMY_MAX_OVERFLOW控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。

    3.使用

    在app.py:

    from flask import Flaskimport configfrom exts import db app = Flask(__name__)  app.config.from_object(config)  # 加载配置文件db.init_app(app)    # db绑定app  @app.route('/')def index():    return "Index"  if __name__ == '__main__':    app.run() 

    4 ORM操作

    4.1 表操作

    4.1.1 创建一个表

    # models文件中from exts import db class User(db.Model):    __tablename__ = "User"    #设置表名    uid = db.Column(db.Integer, primary_key=True)    username = db.Column(db.String(80), unique=True)    email = db.Column(db.String(120), unique=True)     def __init__(self, username, email):        self.username = username        self.email = email     def __repr__(self):        return '' % self.username

    在Flask-SQLAlchemy中,一张表其实就是一个类.跟Django的ORM非常相似.

    注意: 类需要继承db.Model

    完整示例

    创建一个表的过程,有很多坑。所以这里详细记录一下

    首先看一下tree图

    .

    ├── app.py

    ├── config.py

    ├── exts.py

    ├── models.py

    把应用分成4个py文件是为了以后好维护。

    app.py:

    from flask import Flaskimport configfrom exts import dbfrom models import Article  # 坑一 app = Flask(__name__)app.config.from_object(config)  db.init_app(app)  # 坑二   @app.route('/')def index():    db.create_all()  # 坑三    return "Index"  if __name__ == '__main__':    app.run() 

    坑一: 你要创建那个表,你就得导入那个表所在的py文件(即使它在app.py中未被使用),否者不会创建表,且不会报错

    坑二: app.config.from_object(config) 一定要在db.init_app(app)之前,否者会报错

    坑三: db.create_all() 是创建一个表的命令(models中的类不会创建一个表,就好比django用命令行生成表一样),注意一定要在view函数里面写,不然不会创建表,且不会报错.建议在’/'中写,不会重复创建,可以在创建完后删除

    config.py:

    HOST = '127.0.0.1'PORT = '3306'   # 在mysql中使用show global variables like 'port';查看端口DATABASE = 'test'USERNAME = 'root'PASSWORD = '123456' DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(username=USERNAME,                                         password=PASSWORD, host=HOST,                                         port=PORT, db=DATABASE) SQLALCHEMY_DATABASE_URI = DB_URISQLALCHEMY_TRACK_MODIFICATIONS = FalseSQLALCHEMY_ECHO = True

    exts.py:

    from flask_sqlalchemy import SQLAlchemy#此时先不传入appdb = SQLAlchemy()

    models.py:

    from exts import db  class Article2(db.Model):    __tablename__ = 'article'    id = db.Column(db.Integer, primary_key=True)    title = db.Column(db.String(100), nullable=False)    content = db.Column(db.Text, nullable=False)    def __init__(self, title, content):        self.title = title        self.content = content 

    在这里就可以尽情写表了,注意在app.py中引入就行了

    __init__中记得写上字段名,新增数据时要实例化

    数据类型和约束条件在这里:

    # class类中# 使用db.Column(数据类型, 约束条件)创建,比如:uid = db.Column(db.Integer, primary_key=True)

    数据类型

    数据类型说明
    Integer整形(一般是32位)
    SmallInteger整形(一般是16位)
    BigInteger不限制精度的整数
    Float浮点数
    String字符串
    Text文本
    UnicodeUnicode 字符串
    UnicodeTextUnicode 文本
    Date日期(datetime.date)
    Time时间(datetime.time)
    DateTime日期+时间(datetime.datetime)
    Boolean布尔值
    LargeBinary二进制文件
    pickleTypepickle(Python的一个标准库)后的对象

    约束条件

    约束条件说明
    primary_key如果设为 True,这列就是表的主键
    autoincrement如果设为 True,主键自增长
    unique如果设为 True,这列不允许出现重复的值
    index如果设为 True,为这列创建索引,提升查询效率
    nullable如果设为 True,这列允许使用空值;如果设为 False,这列不允许使用空值
    default为这列定义默认值
    doc字段说明

    4.1.2 创建一条记录

    我们现在已经有一张表了,假如我们需要向表中添加数据那么就需要用到

    db.session.add(tab)db.session.commit()

    例子

    注User表和render_template都要我们导入

    @app.route("/register", methods=["get", "post"])def register():    print(request.method)    if request.method == "GET":        return render_template("register.html")    else:        username = request.form.get("username")        password = request.form.get("password")        user_obj = User(username, password)        db.session.add(user_obj)        db.session.commit()        return "ok!"

    特别提示: db.session.add()的参数是一个model对象(表的对象),传错的话会报错

    对于一次性修改多个表的话,可以使用db.session.add_all(), 参数是由表对象组成的可迭代对象(如:[user_obj, article_obj])

    4.2 一对多关系

    4.2.1建立一对多关系

    一对多关系就是字表db.ForeignKey和主表db.relationship一起建立

    db.relationship很重要,后面查询时用到

    from exts import db  class User(db.Model):    __tablename__ = 'user'    nid = db.Column(db.Integer, primary_key=True, autoincrement=True)    username = db.Column(db.String(16), nullable=False)    password = db.Column(db.String(32), nullable=False)    article = db.relationship("Article", backref="user")     def __init__(self, username, password):        self.username = username        self.password = password     def __repr__(self):        return "" % self.username  class Article(db.Model):    __tablename__ = 'Article'    nid = db.Column(db.Integer, primary_key=True, autoincrement=True)    title = db.Column(db.String(36), nullable=False)    content = db.Column(db.Text, nullable=False)    author_id = db.Column(db.Integer, db.ForeignKey("user.nid"))     def __init__(self, title):        self.title = title        self.content = content     def __repr__(self):        return "" % self.title

    坑: 一定要注意db.ForeignKey的参数是 表名.xxx,而且表名是__tablename__,不是类名,大小写敏感,写错会报错

    4.2.2 一对多——增

    一对多增加条记录,会同时修改两个表,但只需要一次bd.session.add()和db.session.commit()

    @app.route("/register", methods=["get", "post"])def register():    print(request.method)    if request.method == "GET":        return render_template("register.html")    else:        username = request.form.get("username")        password = request.form.get("password")        title = request.form.get("title")        content = request.form.get("content")                user_obj = User(username, password)        art_obj = Article(title, content)        user_obj.article = [art_obj]        db.session.add(user_obj)        db.session.commit()        return "ok!"

    注意: relationship字段接收的是一个list

    4.2.3 一对多——删

    步骤:

    1、找到要删除的记录

    2、db.session.delete(a)删除

    3、db.session.commit()保存

    @app.route('/delete_user')def delete_user():    a = db.session.query(User).filter(User.nid == 2).first()    db.session.delete(a)    db.session.commit()    return "ok"

    4.2.4 一对多——改

    @app.route('/update_article')def update_article():    #  方法一    a = db.session.query(Article).get(1)  # 先查询出需要修改的条目    print(a)    Article.query.get(1)    a.title = '母猪产后护理'  # 修改    db.session.commit()     #  方法二    # 直接查询出后修改,update采用字典修改{修要修改的列:'修改后的值'}    db.session.query(Article).filter(Article.nid == 3).update({Article.title: '母猪产后护理'})    db.session.commit()    return 'ok'

    4.2.5 一对多——查

    @app.route('/get_article')def get_article():    #  子查主    #  方法一    user1 = db.session.query(Article).filter(Article.title == '母猪产后护理').first().user    #  方法二    user2 = Article.query.filter(Article.title == '母猪产后护理').first().user    print("user1", user1.username)    print("user2", user2)     #  主查子    #  方法一    article1 = db.session.query(User).filter(User.username == 'lczmx').first().article    #  方法二    article2 = User.query.filter(User.username == 'lczmx').first().article    print(article1)    print(article2)    return "ok"

    这里需要注意的是:

    1、query.filter()后的数据是BaseQuery对象,不能通过‘.外键’的方式取值,要把其变为表的对象后才能‘.’

    2、这里的跨表查询实际上用到的是主表的relationship

    relationship的参数:backref

    ​编辑

    补充:

    relationship的关键字参数cascade

    值说明
    save-update默认选项, 在添加一条数据的时候,会把其他和它相关联的数据都添加到数据库中。这种行为就是save-update属性影响的
    delete表示当删除某一个模型中的数据的时候,是否也删除掉使用relationship和它关联的数据
    delete-orphan表示当对一个ORM对象解除了父表中的关联对象的时候,自己便会被删除掉。当然如果表中的数据被删除,自己也会被删除。这个选项只能用在一对多上,不能用在多对多以及多对一上。并且还需要在子表中的relationship中,增加一个single_parent=True的参数
    merge默认选项, 当在使用session.merge,合并一个对象的时候,会将使用了relationship相关联的对象也进行merge操作
    expunge移除操作的时候,会将相关联的对象也进行移除。这个操作只是从session中移除,并不会真正的从数据库中删除
    all是对save-update,merge,refresh-expire,expunge,delete几种的填写

    比如:

    articles = relationship("Article",cascade="save-update,delete")

    来源:点击这里

    4.2.6 查(不跨表)

    对于普通的单表查找知道在哪里写好,只好这这里记录了。

    假如已经import了User表

    命令说明
    User.query.all()查询所有用户数据
    User.query.count()查询有多少个用户
    User.query.first()查询第1个用户
    User.query.get(1)根据id查询
    User.query.filter_by(id=1).all()根据id查询, 简单查询, 使用关键字实参的形式来设置字段名
    User.query.filter(User.id == 1).all()根据id查询,复杂查询,使用恒等式等其他形式来设置条件
    User.query.filter(User.name.startswith(“l”)).all()开头
    User.query.filter(User.name.endswith(“x”)).all()结尾
    User.query.filter(User.name.contains(“lcz”)).all()包含
    User.query.filter(User.name.like(“%cz%”)).all()模糊查询,点击查看多关键字过滤查询
    User.query.filter(not_(User.name == “lczmx”)).all()取反查询
    User.query.filter(User.name != “lczmx”).all()取反查询
    User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all()查询id为[1, 3, 5, 7, 9]的用户
    User.query.group_by(User.role_id).all()分组查询
    User.query.order_by(User.role_id).all()排序
    .distinct()去重
    .limit(n)取结果的前n个
    .offset(n)跳过前n个
    pn = User.query.paginate((page,per_page,False)分页查询,age:哪一页 per_page:每页多少条,False:查询不到不报错。pn.items 获取该页的数据 pn.page 获取当前的页码 pn.pages 获取总页数
    这篇文章写得很好

    注:和django的ORM一样.all()的是一个由query对象组成的列表,.get()和.first()以及.last()都是query对象

    4.3 一对一关系

    一对一需要设置relationship中的uselist=Flase,其他数据库操作一样。

    4.4 多对多关系

    如果你想要用多对多关系,你需要定义一个用于关系的辅助表。对于这个辅助表, 强烈建议 不 使用模型,而是采用一个实际的表

    4.4.1 建立多对多关系

    使用db.Table

    student2course = db.Table('student2course', db.Column('student_id', db.Integer, db.ForeignKey('student.id')),                db.Column('course_id', db.Integer, db.ForeignKey('course.id')))  class Student(db.Model):    __tablename__ = 'student'    id = db.Column(db.Integer, primary_key=True)    name = db.Column(db.String(12))    course = db.relationship('Course', secondary=student2course)     def __init__(self, name):        self.name = name     def __repr__(self):        return "name:%r" % self.name  class Course(db.Model):    ___tablename__ = 'course'    id = db.Column(db.Integer, primary_key=True)    name = db.Column(db.String(30), unique=True)     def __init__(self, name):        self.name = name     def __repr__(self):        return "name:%r" % self.name

    注:添加多对多的反向引用,必须使用secondary指定中间关联表

    4.4.2 多对多——增

    @app.route("/add")def add():    stu1 = Student("卢来佛祖")    stu2 = Student("乔碧萝")    cou1 = Course("语文")    cou2 = Course("数学")    cou3 = Course("英语")    stu1.course = [cou1, cou2]    stu2.course = [cou1, cou2, cou3]    db.session.add_all([stu1, stu2])    db.session.commit()    return "ok"

    可以发现,使用的就是一对多的方法,实际上多对多就是两个一对多

    另一种情况

    假如为已经在表中的数据添加关系

    @app.route("/update")def update():    cou1 = Course.query.filter_by(id=2).first()    stu1 = Student.query.get(1)    stu1.course.append(cou1)    db.session.add(stu1)    db.session.commit()    return "ok" 

    4.4.3 多对多——删

    @app.route("/delete")def delete():    cou = Course.query.get(2)    stu = Student.query.get(1)    stu.course.remove(cou)    db.session.commit()    return "ok"

    假如使用Student.query.filter(Student.id == 2).first().course.remove(cou),这样一条代码写完的话会报错,不知道为什么

    报错提示:sqlalchemy.orm.exc.ObjectDereferencedError: Can’t emit change event for attribute ‘Student.course’ - parent object of type has been garbage collected.

    5 db的方法总结

    方法说明
    .create_all()创建所有表
    .drop_all()删除所有表
    .init_app(app)初始化应用程序

    八、数据库迁移更新

    1.安装flask-migrate组件

    pip install flask-migrate

    2.创建同步对象

    migrate=migrate(app,db)

    3.同步操作

    3.1 创建同步

    flask db init #只需要执行一次

    3.2增量更新操作

    flask db migrate

    3.3同步到数据库

    flask db upgrate

    ​

    如果你对Python感兴趣,想要学习python,这里给大家分享一份Python全套学习资料,都是我自己学习时整理的,希望可以帮到你,一起加油!

    有需要的小伙伴,可以V扫描下方二维码免费领取

    ​

    1️⃣零基础入门

    ① 学习路线

    对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

    ② 路线对应学习视频

    还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~

    ③练习题

    每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!

    Python兼职渠道推荐

    学的同时助你创收,每天花1-2小时兼职,轻松稿定生活费.

    2️⃣国内外Python书籍、文档

    ① 文档和书籍资料

    3️⃣Python工具包+项目源码合集

    ①Python工具包

    学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!

    ②Python实战案例

    光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!

    ③Python小游戏源码

    如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!

    4️⃣Python面试题

    我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

    上述所有资料 ⚡️ ,朋友们如果有需要的,可以扫描下方二维码免费领取

    ​

    上一篇:独家揭秘,轻松免费下载MSVOD秘籍!

    下一篇:CER下载指南,简洁教程,一键轻松获取