Python-Flask 快学

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/<username>")
def user_info(username):return "hello %s" % username

2.2限定类型

@app.route("/user/<string:username>")
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 BaseConverter
app = 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/<re('lcz.{2}'):username>")
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":passelse:pass

注意request是需要从falsk中导入

三、响应规则

1.html

1.1 html文本

@app.route("/user")
def user():return "<h1>User Info</h1>"

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 redirect
from flask import url_for@app.route("/user/<int:user_id>")
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/<int:user_id>")
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) }}
禁用转义:{{ '<em>hello</em>' | safe }}
删除标签:{{ '<em>hello</em>' | 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 %}<li>{{ user_info.msg1 }}</li>{% elif user_info.nid == 20%}<li>{{ user_info.msg2 }}</li>{% else %}<li>{{ user_info.msg3 }}</li>
{% endif %}

4.2 for

{% for name in name_list %}<li>{{ name }}</li>
{% endfor %}

不能使用continue和break

注:
在for中有一个关键字叫loop,使用loop可以查看当前的迭代状态
下面列出我认为有用的loop方法

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

5.导入

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

{% include "layout.html" %}

6 继承

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

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
{% block title %}
{% endblock %}
<div><h1>今天是个好日子</h1>
</div>
{% block  content%}<h3>我是内容</h3>
{% endblock %}
{% block js %}
<script src="../static/js/jquery.js"></script>
{% endblock %}
</body>
</html>

用block留出填充部分

{% extends "base.html" %}
{% block title %}<h1>啦啦啦</h1>
{% 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 = True
SECRET_KEY = 'SECRET_KEY粘贴在这里'

在app.py中

import configapp.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-mysqldb
pip install flask-mysqldb
# 提示:如果flask-mysqldb安装不上,安装, pip install pymysql 

2 配置

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

exts.py:

from flask_sqlalchemy import SQLAlchemydb = 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_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_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 Flask
import config
from exts import dbapp = 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 dbclass 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 = usernameself.email = emaildef __repr__(self):return '<User %r>' % self.username

在Flask-SQLAlchemy中,一张表其实就是一个类.跟Django的ORM非常相似.
注意: 类需要继承db.Model

完整示例

创建一个表的过程,有很多坑。所以这里详细记录一下
首先看一下tree图
.
├── app.py
├── config.py
├── exts.py
├── models.py
把应用分成4个py文件是为了以后好维护。
app.py:

from flask import Flask
import config
from exts import db
from 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_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True

exts.py:

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

models.py:

from exts import dbclass 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 = titleself.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 dbclass 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 = usernameself.password = passworddef __repr__(self):return "<User %s>" % self.usernameclass 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 = titleself.content = contentdef __repr__(self):return "<User %s>" % 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().userprint("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().articleprint(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-updatemergerefresh-expireexpungedelete几种的填写

比如:

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 = namedef __repr__(self):return "name:%r" % self.nameclass 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 = namedef __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之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/732057.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20240309-2-校招前端面试常见问题-NodeJS

校招前端面试常见问题【6】——NodeJS NodeJS Q&#xff1a;NodeJS 的 IO 模型特点是什么&#xff1f;与多线程同步 IO 有什么不同&#xff1f; NodeJS 的 IO 模型&#xff08;更准确的说是 js 的执行环境&#xff0c;也就是 v8&#xff09;的特点是“单线程异步非阻塞”。 …

Linux学习-共用体和枚举,位运算

目录 共用体 ​编辑枚举 位运算 共用体 定义和访问都和结构体类似&#xff1b;区别在于共用体所有的成员变量共享同一片空间&#xff0c;内存空间就是其最大数据类型所占内存的大小&#xff1b; 如果给成员变量2的值&#xff0c;那么成员变量1的值就会被覆盖&#xff1b;主…

实现鼠标移动el-select下拉框的label上面显示出table悬浮窗

首先是对vue代码 实现思路就是在el-option里面放一个span来包裹el-popover&#xff0c;里面在放tabe实现悬浮表格 <el-form-item label"原理图编号"><el-select v-model"data.number" placeholder"请选择" clearable multiple collaps…

外包干了30天,我后悔了。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 这次来聊一个大家可能也比较关心的问题&#xff0c;那就是就业城…

枚举赋值及强制转换问题

对枚举进行字符赋值&#xff0c;需要进行强制类型转换之后&#xff0c;才能得到想要的值&#xff0c;如下 typedef enum data {DIRECTION_X X,DIRECTION_Y Y,DIRECTION_Z Z,DIRECTION_T T }NumData;int main() {NumData numdata DIRECTION_Y;count <<"num is&…

第九篇 – 过程发现(Process Discovery)是如何赋能数字化市场营销全过程?- 我为什么要翻译介绍美国人工智能科技巨头IAB公司

IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&#xff09;自1996年成立以来&#xff0c;先后为700多家媒体…

电路板故障的四大原因--芯片级维修

电路板是我们日常使用的技术的核心。 手机、电视、车辆、路灯和大量其他物品都依赖于电路板&#xff0c;这就是为什么故障可能具有高度破坏性。 电路板出现故障的原因有多种&#xff0c;与潮湿、高温和污垢等常见因素有关。 了解电路板故障的原因可以让您避免未来的故障&#x…

波奇学Linux: 信号捕捉

sigaction:修改信号对应的handler方法 act输入型参数&#xff0c;oldact输出型参数 void (*sa_handler) (int) //修改的自定义函数 sigset_t sa_mask // void handler(int signo) {cout<<"catch a signal, signal number: "<<signo<<endl; } int …

WindTerm的安装及远程连接Linux系统步骤

文章目录 WindTerm下载WindTerm远程连接Linux WindTerm下载 官网下载链接 WindTerm网盘下载链接 WindTerm不需要安装&#xff0c;将下载的压缩包解压后直接找到WindTerm.exe执行文件&#xff0c;双击即可运行 WindTerm远程连接Linux 1.先获取你的Linux的IP地址&#xff0c;…

【高效开发工具系列】Windows 系统下将 Windows 键盘的 ctrl 和 alt 互换

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Mysql深入学习 基础篇 Ss.06 事务

青青子衿&#xff0c;悠悠我心 纵我不往&#xff0c;子宁不嗣音 —— 24.3.9 事务&#xff1a; 事务简介 事务操作 事务四大特性 并发事务问题 事务隔离级别 一、事务简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整…

【蓝桥杯-单片机】LED和按键小练习:Led彩灯控制系统

文章目录 【蓝桥杯-单片机】LED和按键小练习&#xff1a;Led彩灯控制系统01 题目描述02 题目解答03 本题总结整体逻辑框架&#xff08;详细版&#xff09;整体逻辑框架&#xff08;缩略版&#xff09;按键读取模块按键消抖模块流水灯显示模式&#xff08;1&#xff09;从上向下…

基于SVM模型的网络入侵检测模型训练与评估(NSL-KDD数据集)

简介 针对网络安全领域的NSL-KDD数据集进行分类任务的预处理和模型训练、以及超参数调优。 数据预处理 读取并解析数据集&#xff1b;检查并删除指定列&#xff08;outcome&#xff09;的缺失值&#xff1b;对类别型特征&#xff08;protocol_type, service, flag&#xff0…

GPT-4 等大语言模型(LLM)如何彻底改变客户服务

GPT-4革命&#xff1a;如何用AI技术重新定义SEO策略 在当今快节奏的数字时代&#xff0c;客户服务不再局限于传统的电话线或电子邮件支持。 得益于人工智能 (AI) 和自然语言模型 (NLM)&#xff08;例如 GPT-4&#xff09;的进步&#xff0c;客户服务正在经历革命性的转变。 在这…

【Python】成功解决NameError: name ‘a‘ is not defined

【Python】成功解决NameError: name ‘a’ is not defined &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您的订…

gensim 实现 TF-IDF;textRank 关键词提取

目录 TF-IDF 提取关键词 介绍 代码 textRAnk 提取关键词 这里只写了两种简单的提取方法&#xff0c;不需要理解上下文&#xff0c;如果需要基于一些语义提取关键词用 LDA&#xff1a;TF-IDF&#xff0c;textRank&#xff0c;LSI_LDA 关键词提取-CSDN博客 TF-IDF 提取关键词…

MySQL中批量修改某个字段的一部分字符,可以使用UPDATE语句结合REPLACE函数

示例语句 UPDATE your_table_name SET your_column_name REPLACE(your_column_name, old_string, new_string) WHERE your_column_name LIKE %old_string%; 原因&#xff1a; 项目用了一个服务上传地址原来是http开头&#xff0c;数据库存的地址也是http&#xff0c;后来加了…

基于java EE医疗机械设备采购管理系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 系统开发相关技术 3 1.1 J2EE技术简介 3 1.2 SSH框架技术 3 1.3 JQuery技术 3 1.4 CSS技术 3 1.5 XML技术 3 1.6 Ajax技术 4 1.7 MySQL数据库 4 1.8 本章小结 4 2 系统分析 5 2.1 概要分析 5 2.2 功能需求分析 6 2.3 功能初步设计 6 2.4 …

COMSOL热应力仿真

热应力 热膨胀子节点 热膨胀输入类型 假如直接知道热膨胀大小&#xff0c;可以直接对热应变进行赋值。 约束与载荷 对于自由膨胀&#xff0c;可以添加抑制刚体运动。 案例分析 在参数部分&#xff0c;设定体积参考温度Tref&#xff0c;假定在25[degC]模型无热应变。 APP开发器-…

vue 使用 PrintJs 实现打印pdf效果

一、print.js介绍 Print.js主要是为了帮助我们直接在应用程序中打印PDF文件&#xff0c;而无需离开界面&#xff0c;并且不使用嵌入。对于用户不需要打开或下载PDF文件的特殊情况&#xff0c;他们只需要打印它们。 例如&#xff0c;当用户请求打印在服务器端生成的报告时&…