Flask框架学习记录
Flask项目简要
项目大致结构
flaskDemo1
├─static
├─templates
└─app.py
app.py
# 从flask这个包中导入Flask类
from flask import Flask# 使用Flask类创建一个app对象
# __name__:代表当前app.py这个模块
# 1.以后出现bug,可以帮助快速定位
# 2.对于寻找模板文件,有一个相对路径
app = Flask(__name__)# 创建一个路由和视图函数的映射
@app.route('/')
def hello_world():return 'https://blog.csdn.net/m0_61465701?type=blog'if __name__ == '__main__':app.run()
运行结果:
FLASK_APP = app.py
FLASK_ENV = development
FLASK_DEBUG = 0
In folder E:/PyCharmProject/flaskDemo1
E:\SoftwareFile\anaconda\python.exe -m flask run * Serving Flask app "app.py"* Environment: development* Debug mode: off* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
可以进入网站查看效果。
debug模式
开启debug模式后
- 只要修改代码后保存,就会自动重新加载,不需要手动重启项目。
- 在浏览器上就可以看到出错信息。
开启:
点击Edit Configurations… , 再勾选Configuration下的FLASK_DEBUG选项,点击OK。
社区版:修改代码
app.run(debug=True)
修改代码后,ctrl+s保存后就会自动重新加载。
* Detected change in 'E:\\PyCharmProject\\flaskDemo1\\app.py', reloading* Restarting with watchdog (windowsapi)* Debugger is active!* Debugger PIN: 296-639-520* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
修改host
主要作用:就是让其他电脑能访问到自己电脑上的flask项目
点击Edit Configurations… , 在Configuration下的Additional options中填写即可
--host=0.0.0.0 //可以写自己电脑的ip地址
// 0.0.0.0别人可以访问你电脑上的
修改port端口号
点击Edit Configurations… , 在Configuration下的Additional options中填写
--host=0.0.0.0 --port=8000
URL与视图的映射
url: http[80]/https[443]://www.xxx.com:443/path (冒号应为英文的:)
url与视图更准确来说是path与视图,只有path部分是需要自己现在编写的。
绝大部分网站都不可能只有首页一个页面,我们在制作网站的时候,需要定义许多不同的URL来满足需求,而URL总体上来讲又分为两种,第一种是无参数的,第二种是有参数的。
定义无参URL
无参URL是在URL定义的过程中,不需要定义参数。
可以使用以下代码实现。
@app.route('/2')
def stage2():return 'stage2'@app.route('/3/abc')
def stage3():return 'stage3--abc'
注意:我们说的访问/path是不包含域名和端口号的,真正在浏览器中访问应该在前面加上域名和端口号,比如在本地开发应该为http://127.0.0.1:5000/path ,下文说的URL都是省略了域名和端口号。
定义带有参数的URL
很多时候,我们在访问某个URL的时候,需要携带一些参数过去。
比如获取博客详情,就需要把博客的id传过去,那么博客详情的URL可能为:/blog/13,其中13为博客的id。比如获取第10页的博客列表,那么博客列表的URL可能为: /blog/list/10,其中10为页码。
在Flask中,如果URL中携带了参数,那么视图函数也必须定义相应的形参来接收URL中的参数。
@app.route('/test/<int:num>')
def show(num):return "num=%s" % num
可以看到,URL中多了一对尖括号,并且尖括号中多了一个num,这个 num就是参数。然后在视图函数 show中,也相应定义了一个num的形参,当浏览器访问这个URL的时候,Flask接收到请求后,会自动解析URL中的参数 num,然后把他传给视图函数 show,在视图函数中,开发者就可以根据这个num,从数据库中查找到具体的数据,返回给浏览器。
参数类型可以不指定。
URL中的参数可以指定以下类型
参数类型 | 描述 |
---|---|
string | 字符串类型。可以接受除/以外的字符 |
int | 整型。可以接受通过int()方法转换的字符 |
float | 浮点类型。以接受通过float()方法转换的字符 |
path | 路径。类似string,但是中间可以添加/。 |
uuid | UUID类型。UUID是一组由32位数的16进制所构成。 |
any | 备选值中的任何一个。 |
比较特殊的any举例:
@app.route('/<any(a,b,c):s>')
def show2(s):return "str=%s" % s
查询字符串的方式传参
from flask import Flask,request...@app.route('/num1')
def show3():# arguments:参数# request.args:类字典类型num = request.args.get("num",default=555,type=int)return f"num={num}"
在浏览器访问http://127.0.0.1:5000/num1 结果为
num=555
在浏览器访问http://127.0.0.1:5000/num1?num=123结果为
num=123
Jinja2模板
在Flask中,渲染HTML通常会交给模板引擎来做,而Flask中默认配套的模板引擎是Jinja2,Jinja2的作者也是Flask的作者,Jinja2可以独立于Flask使用,比如被Django使用。Jinja2是一个高效、可扩展的模板引擎。
模板渲染
在templates下新建一个html文件,index.html
<!--html 5的标签-->
<!DOCTYPE html>
<html lang="en">
<head><!--页面的字符集--><meta charset="UTF-8"><title>标题</title>
</head>
<body><h1>标题 h1</h1>
<hr><p>HTML 是一门语言,所有的网页都是有HTML这门语言编写出来的。<br>HTML 是一门语言,所有的网页都是有HTML这门语言编写出来的。
</p></body>
</html>
然后修改app.py中的代码
from flask import Flask,request,render_templateapp = Flask(__name__)@app.route('/test1')
def test1():return render_template("index.html")if __name__ == '__main__':app.run(debug=True)
渲染变量
html文件:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>博客详情</title>
</head>
<body><h1>用户名:{{ username }}</h1>
<h1>访问的博客详情是:{{ blog_id }}</h1></body>
</html>
修改app.py:
@app.route('/blog/<blog_id>')
def blog_detail(blog_id):return render_template("blog_detail.html",blog_id=blog_id,username='Xiaoming')
模板访问对象属性
类
index.html:
<!--html 5的标签-->
<!DOCTYPE html>
<html lang="en">
<head><!--页面的字符集--><meta charset="UTF-8"><title>标题</title>
</head>
<body><h1>用户名/邮箱</h1><h2>{{ user.username }}/{{ user.email }}</h2></body>
</html>
app.py:
app = Flask(__name__)class User:def __init__(self,username,email):self.username = usernameself.email = email@app.route('/test2')
def test2():user = User(username="Xiaoming",email="2023@qq.com")return render_template("index.html",user=user)
字典
index.html:
<h1>用户名/邮箱</h1><div>{{ user.username }}/{{ user.email }}</div><div>{{ person['username'] }}/{{ person.email }}</div>
app.py:
app = Flask(__name__)class User:def __init__(self,username,email):self.username = usernameself.email = email@app.route('/test2')
def test2():user = User(username="Xiaoming",email="2023@qq.com")person = {"username":"Wang Xiaoming","email":"2009@qq.com"}return render_template("index.html",user=user,person=person)
过滤器的使用
在Python中,如果需要对某个变量进行处理。我们可以通过函数来实现。在模板中,我们则是通过过滤器来实现的。过滤器本质上也是函数。但是在模板中使用的方式是通过管道符号|来调用的。
例如有个字符串类型变赋 name。想要获取他的长度。则可以通过{{ name |length}}来获收。Jinja2会把name当傲第一个参数传给 length过滤器底层对应的函数。
新建filter.html文件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>过滤器使用</title>
</head>
<body>{{ user.username }}-长度为:{{ user.username|length }}
<br>
{{ user.email }}-长度为:{{ user.email|length }}</body>
</html>
修改app.py
@app.route('/filter')
def filter_demo():user = User(username="Zhang",email="1999@qq.com")return render_template("filter.html",user=user)
一些过滤器
abs(value):返回一个数值的绝对值,例如
{{ -1|abs }}
。如果给的参数类型不为数字,就会报错。default(value,default_value,boolean=False):如果value没有定义,则返回第二个参数default_value。如果想要让 value在被判断为False的情况下(传入
'',[],None,{}
这些值的时候)使用default_value,则应该将后面的boolean参数设置为True。escape(value):将一些特殊字符,比如:&,<,>,",'进行转义。因为Jinja2默认开启了全局转义,所以在大部分情况下无需手动使用这个过滤器去转义,只有在关闭转义的情况下会需要使用。
first(value): 返回序列的第一个元素
- 如果是一个字典,那么返回的是
key
的值
- 如果是一个字典,那么返回的是
last(value): 返回序列的最后一个元素
format(value,*args,**kwargs): 格式化字符窜,和python中写法是一样的。
{{ "%s/%s"|format("username","email") }}
join(value,d=’’): 将一个序列用d这个参数的值拼接成字符串
num=[1,2,3,4]
{{ num|join('-') }}
结果: 1-2-3-4
自定义过滤器
如果内置过滤器不满足需求,我们还可以自定义过滤器。
过滤器本质上是 Python的函数,他会把被过滤的值当做第一个参数传给这个函数,函数经过一些逻辑处理后,再返回新的值。在过滤器函数写好后,可以通过@app.template_ filter装饰器或者是 app.add_template_filter 函数来把函数注册成Jinja2能用的过滤器。
def add_string(value, mystr):return value+mystrapp.add_template_filter(add_string,"addstring")
其中第一个参数是需要被处理的值,然后通过app.add_template_filter,将函数注册成了过滤器,并且这个过滤器的名字,叫做addstring。那么以后在模板文件中,就可以使用了:
{{ user.username|addstring("hhhh") }}
如果app.add_template_filter没有传第二个参数,那么默认将使用函数的名称,来作为过滤器的名称。
app.add_template_filter(add_string)
{{ user.username|add_string("hhhh") }}
控制语句
if语句
Jinja2中的if语句和Python中的if语句非常的类似。可以使用>、<、>=、<=、==、!=来进行判断,也可以通过and、or、not来进行逻辑操作。
control.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>控制语句</title>
</head>
<body>
{% if a > 20 %}<div>a的值大于20</div>
{% elif a == 20%}<div>a的值等于20</div>
{% else %}<div>a的值小于20</div>
{% endif %}
</body>
</html>
app.py
@app.route('/control')
def control_statement():a = 22return render_template("control.html",a = a)
for循环
Jinja2中的 for循环与Python中的 for 循环也是非常类似的,只是比 Python中的 for 循环多一个endfor 代码块。
不存在break语句。
control.html
{% for person in persons %}<div>name:{{ person.name }},hobby:{{ person.hobby }}</div>
{% endfor %}
app.py
@app.route('/control')
def control_statement():a = 22persons = [{"name":"Xiaoming","hobby":"baseball"},{"name":"Xiaofang","hobby":"basketball"}]return render_template("control.html",a = a,persons = persons)
模板继承
一个网站中,大部分网页的模块是重复的,比如顶部的导航栏,底部的备案信息。如果在每个页面中都重复的去写这些代码,会让项目变得臃肿,提高后期维护成本。比较好的做法是,通过模板继承,把一些重复性的代码写在父模板中,子模板继承父模板后,再分别实现自己页面的代码。
新建一个base.html作为父模板
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{% block title %}{% endblock %}</title>
</head>
<body>
<ul><li><a href="#">首页</a></li><li><a href="#">其他</a></li>
</ul><p>父模板的文字</p>
{% block body %}
{% endblock %}
<footer>底部标签</footer>
</body>
</html>
以上父模板中,编写好了网页的整体结构。然后针对子模板需要重写的地方,则定义成了block,比如以上定义了title、body这两个block,子模板在继承了父模板后,重写对应 block 的代码,即可完成子模板的渲染。
编写一个child1.html
{% extends "base.html" %}{% block title %}child1标题
{% endblock %}{% block body %}<p>子模版child1的部分</p>
{% endblock %}
app.py:
@app.route("/child1")
def child1():return render_template("child1.html")
加载静态文件
一个网页中,除了HTML代码以外,还需要CSS、JavaScript 和图片文件才能更加美观和实用。静态文件默认是存放到当前项目的static文件夹中,如果想要修改静态文件存放路径,可以在创建Flask对象的时候,设置static_folder 参数。
app = Flask(__name__,static_folder='C:\\Users\\Xu\\Desktop\\static')
在模板文件中,可以通过url_for加载静态文件,示例代码如下。
<link rel="stylesheet" href="{{ url_for('static',filename='style.css') }}">
第一个参数static是一个固定的,表示构建Flask 内置的static视图这个URL,第二个filename 是可以传递文件名或者文件路径,路径是相对于static或者static_folder参数自定义的路径。以上代码在被模板渲染后,会被解析成:
<link href="/static/style.css">
新建一个style.css文件
body{background: antiquewhite;
}
新建一个jstest.js文件
alert("it is js")
新建一个static.html文件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>加载静态文件</title><link rel="stylesheet" href="{{ url_for('static',filename='css/style.css') }}"></head>
<body>
<img src="{{ url_for('static',filename='images/city.png') }}" alt="">
<script src="{{ url_for('static',filename='js/jstest.js') }}">
</script>
</body>
</html>
修改app.py
@app.route("/static")
def static_demo():return render_template("static.html")
数据库
数据库是一个动态网站必备的基础功能。通过使用数据库,数据可以被动态的展示、修改、删除等,极大的提高了数据管理能力,以及数据传递的效率。
Flask想要操作数据库,必须要先安装Python操作 MySQL的驱动。在Python中,目前有以下MySQL驱动包。
MySQL-python:也就是 MySQLdb。是对C语言操作 MySQL数据库的一个简单封装。遵循了Python DB·API v2。但是只支持Python2。
mysqIclient:是 MySQL-python的另外一个分支。支持Python3并且修复了一些bug,是目前为止执行效率最高的驱动,但是安装的时候容易因为环境问题出错。
pymysql:纯 Python实现的一个驱动。因为是纯 Python编写的,因此执行效率不如 mysqlclient。也正因为是纯 Python写的,因此可以和Python代码无缝衔接。
mysql-connector-python: MySQL官方推出的纯 Python连接MySQL 的驱动,执行效率比pymysql 还慢。
这里我们用的是pymysql
通过以下命令安装。
pip install pymysql
在Flask中,我们很少会使用pymysql直接写原生SQL语句去操作数据库,更多的是通过SQLAlchemy提供的ORM技术,类似于操作普通Python对象一样实现数据库的增删改查操作,而 Flask-SQLAlchemy是对 SQLAIchemy的一个封装,使得在Flask中使用SQLAlchemy更加方便。
Flask-SQLAlchemy是需要单独安装,因为Flask-SQLAlchemy依赖SQLAlchemy,所以只要安装了Flask-SQLAlchemy,sQLAlchemy会自动安装。安装命令如下。
pip install flask-sqlalchemy
SQLAlchemy类似于Jinja2,是可以独立于Flask而被使用的,完全可以在任何Python程序被使用,SQLAlchemy的功能非常强大。
SQLAlchemy 的官方文档。
Flask连接MySQL数据库
使用 Flask-SQLAlchemy操作数据库之前,要先创建一个由 Flask-SQLAlchemy提供的SQLAlchemy类的对象。在创建这个类的时候,要传入当前的app。然后还需要在app.config中设置SQLALCHEMY_ DATABASE_URI,来配置数据库的连接。
修改app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# MySQL所在的主机名
HOSTNAME = "127.0.0.1"
# MySQL监听的端口号,默认3306
PORT = 3306
# 连接MySQL的用户名
USERNAME = "root"
# 连接MySQL的密码
PASSWORD = "031006"
# MySQL上创建的数据库名称
DATABASE = "xlr"app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"# 在app.config中设置好连接数据库的信息,
# 然后使用SQLAlchemy(app)创建一个db对象
# SQLAlchemy会自动读取app.config中连接数据库的信息db = SQLAlchemy(app)# 测试数据库是否连接成功
# 连接成功后结果为(1,)
with app.app_context():with db.engine.connect() as conn:rs = conn.execute("select 1")print(rs.fetchone())@app.route('/')
def hello_world(): # put application's code herereturn 'Hello World!'if __name__ == '__main__':app.run()
ORM模型与表的映射
对象关系映射(Object Relationship-Mapping),简称ORM,是一种可以用Python面向对象的方式来操作关系型数据库的技术,具有可以映射到数据库表能力的 Python类我们称之为ORM模型。一个ORM模型与数据库中一个表相对应,ORM模型中的每个类属性分别对应表的每个字段,ORM模型的每个实例对象对应表中每条记录。ORM技术提供了面向对象与SQL交互的桥梁,让开发者用面向对象的方式操作数据库,使用ORM模型具有以下优势。
- 开发效率高:几乎不需要写原生SQL语句,使用纯 Python的方式操作数据库,大大的提高了开发效率。
- 安全性高:ORM模型底层代码对一些常见的安全问题,比如SQL注入做了防护,比直接使用SQL语句更加安全。
- 灵活性强:Flask-SQLAlchemy底层支持SQLite、MySQL、Oracle、PostgreSQL等关系型数据库,但针对不同的数据库,ORM模型代码几乎一模一样,只需修改少量代码,即可完成底层数据库的更换。
修改app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# MySQL所在的主机名
HOSTNAME = "127.0.0.1"
# MySQL监听的端口号,默认3306
PORT = 3306
# 连接MySQL的用户名
USERNAME = "root"
# 连接MySQL的密码
PASSWORD = "031006"
# MySQL上创建的数据库名称
DATABASE = "xlr"app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"# 在app.config中设置好连接数据库的信息,
# 然后使用SQLAlchemy(app)创建一个db对象
# SQLAlchemy会自动读取app.config中连接数据库的信息db = SQLAlchemy(app)# 测试数据库是否连接成功
# 连接成功后结果为(1,)
# with app.app_context():
# with db.engine.connect() as conn:
# rs = conn.execute("select 1")
# print(rs.fetchone())# User继承自db.Model
# db.Model中封装了与数据库底层交互相关的一些方法和属性
class User(db.Model):__tablename__ = 'user'id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 这样id才能成为表中的一个字段# varchar 最大长度为100 nullable=False字段不能为空username = db.Column(db.String(100), nullable=False)password = db.Column(db.String(100), nullable=False)# user = User(username="2021",password="123456")
# sql: insert user(username, password) values('2021', '123456');with app.app_context():db.create_all()@app.route('/')
def hello_world(): # put application's code herereturn 'Hello World!'if __name__ == '__main__':app.run()
首先我们创建一个类名叫 User,并使得他继承自db.Model,所有ORM 模型必须是db.Model的直接或者间接子类。
然后通过_tablename_属性,指定User模型映射到数据库中表的名称。
接着我们定义了三个db.Column类型的类属性,分别是id、username、password,只有使用db.Column定义的类属性,才会被映射到数据库表中成为字段。在这个User模型中,id是 db.Integer类型,在数据库中将表现为整形,并且传递primary_key=True参数来指定id作为主键,传递autoincrement=True来设置id为自增长。接下来的username和password,我们分别指定其类型为db.String类型,在数据库中将表现为varchar类型,并且指定其最大长度为100。
ORM模型的CRUD操作
增加操作
先使用ORM模型创建一个对象,然后添加到会话中,再进行commit 操作即可。
修改app.py
class User(db.Model):__tablename__ = 'user'id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 这样id才能成为表中的一个字段# varchar 最大长度为100 nullable=False字段不能为空username = db.Column(db.String(100), nullable=False)password = db.Column(db.String(100), nullable=False)@app.route('/user/add')
def user_add():# 1. 创建ORM对象user = User(username="2021", password="123456")# 2. 将ORM对象添加到db.session中db.session.add(user)# 3. 将db.session中的改变同步到数据库中db.session.commit()return "Add success!"
查询操作
ORM模型都是继承自db.Model,db.Model内置的query属性上有许多方法,可以实现对ORM模型的查询操作。query 上的方法可以分为两大类,分别是提取方法以及过滤方法。
query常用的提取方法
方法名 | 描述 |
---|---|
query.all() | 获取查询结果集中的所有对象,是列表类型。 |
query.first() | 获取结果集中的第一个对象。 |
query.one() | 获取结果集中的第一个对象,如果结果集中对象数量不等于1,则会抛出异常。 |
query.one_or_none() | 与one类似,结果不为1的时候,不是抛出异常,而是返回None。 |
query.get(pk) | 根据主键获取当前ORM模型的第一条数据。 |
query.exists() | 判断数据是否存在。 |
query.count() | 获取结果集的个数。 |
query常用的过滤方法
方法名 | 描述 |
---|---|
query.filter() | 根据查询条件过滤 |
query.filter_by() | 根据关键字参数过滤。 |
query.slice(start,stop) | 对结果进行切片操作。 |
query.limit(limit) | 对结果数量进行限制。 |
query.offset(offset) | 在查询的时候跳过前面offset条数据。 |
query.order_by() | 根据给定字段进行排序。 |
query.group_by() | 根据给定字段进行分组。 |
@app.route('/user/query')
def user_query():# 1. get查找:根据主键查找,只查找一条数据# user = User.query.get(1)# print(f"id:{user.id},username:{user.username},password:{user.password}")# 2. filter_by查找users = User.query.filter_by(username='2021')# 是一个Query对象:类数组for user in users:print(f"id:{user.id},username:{user.username},password:{user.password}")return "Query Success"
更新操作
@app.route('/user/update')
def user_update():user = User.query.filter_by(username='2021').first()user.password = "555555"db.session.commit()return "Update success"
删除操作
@app.route('/user/delete')
def user_delete():# 1. 查找user = User.query.get(1)# 2. 从db.session中删除db.session.delete(user)# 3. 将db.session中的修改,同步到数据库中db.session.commit()return "Delete Success"
ORM模型外键与表关系
关系型数据库一个强大的功能,就是多个表之间可以建立关系。
比如文章表中,通常需要保存作者数据,但是我们不需要直接把作者数据放到文章表中,而是通过外键引用用户表。这种强大的表关系,可以存储非常复杂的数据,并且可以让查询非常迅速。在 Flask-SQLAIchemy中,同样也支持表关系的建立。
表关系建立的前提,是通过数据库层面的外键实现的。表关系总体来讲可以分为三种,分别是:一对多(多对一)、一对一、多对多。
建立关系
class Article(db.Model):__tablename__ = "article"id = db.Column(db.Integer, primary_key=True, autoincrement=True)title = db.Column(db.String(200), nullable=False)content = db.Column(db.Text, nullable=False)# 添加外键author_id = db.Column(db.Integer, db.ForeignKey("user.id"))# 通过db.relationship与User模型建立联系author = db.relationship("User")
我们添加了一个author 属性,这个属性通过db.relationship 与User模型建立了联系,以后通过Article 的实例对象访问author 的时候,比如 article.author,那么Flask-SQLAlchemy会自动根据外键author_id 从 user表中寻找数据,并形成User模型实例对象。
建立双向关系
现在的Article模型可以通过author属性访问到对应的User实例对象。但是User实例对象无法访问到和他关联的所有Article 实例对象。因此为了实现双向关系绑定,我们还需要在User模型上添加一个db.relationship类型的articles属性,并且在User模型和Article模型双方的db.relationship 上,都需要添加一个back _populates参数,用于绑定对方访问自己的属性。
class User(db.Model):__tablename__ = 'user'id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 这样id才能成为表中的一个字段# varchar 最大长度为100 nullable=False字段不能为空username = db.Column(db.String(100), nullable=False)password = db.Column(db.String(100), nullable=False)articles = db.relationship("Article", back_populates="author")class Article(db.Model):__tablename__ = "article"id = db.Column(db.Integer, primary_key=True, autoincrement=True)title = db.Column(db.String(200), nullable=False)content = db.Column(db.Text, nullable=False)# 添加外键author_id = db.Column(db.Interger, db.ForeignKey("user.id"))# 通过db.relationship与User模型建立联系author = db.relationship("User", back_populates="articles")
以上User和Article模型中,我们通过在两边的db.relationship上,传递back_populates参数来实现双向绑定,这种方式有点啰嗦,我们还可以通过只在一个模型上定义db.relationship类型属性,并且传递 backref参数,来实现双向绑定。
class User(db.Model):__tablename__ = 'user'id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 这样id才能成为表中的一个字段# varchar 最大长度为100 nullable=False字段不能为空username = db.Column(db.String(100), nullable=False)password = db.Column(db.String(100), nullable=False)# articles = db.relationship("Article", back_populates="author")class Article(db.Model):__tablename__ = "article"id = db.Column(db.Integer, primary_key=True, autoincrement=True)title = db.Column(db.String(200), nullable=False)content = db.Column(db.Text, nullable=False)# 添加外键author_id = db.Column(db.Interger, db.ForeignKey("user.id"))# backref:会自动的给User模型添加一个articles的属性,用来获取文章列表author = db.relationship("User", backref="articles")
增加和查询article:
@app.route("/article/add")
def article_add():article1 = Article(title="Flask学习", content="Flaskxxxx")article1.author = User.query.get(2)article2 = Article(title="Django学习", content="Django最全学习")article2.author = User.query.get(2)# 添加到session中db.session.add_all([article1, article2])# 同步session中的数据到数据库中db.session.commit()return "Articles Add Success!"@app.route("/article/query")
def query_article():user = User.query.get(2)for article in user.articles:print(article.title)return "Article Query Success!"
flask-migrate迁移ORM模型
采用’db.create_all’在后期修改数据库表字段的时候,不会自动的映射到数据库中,必须删除表,然后重新运行’db.create_all’ 才会重新映射。
这样不符合我们的要求,因此flask-migrate就是为了解决这个问题。它可以在每次修改模型后,将修改的字段映射到数据库中。
安装
进入终端,输入
pip install flask-imgrate
使用
...
from flask_migrate import Migrate...db = SQLAlchemy(app)migrate = Migrate(app, db)...
ORM模型映射成表的三步
flask db init:创建迁移环境 ,迁移环境只需要创建一次。这会在你的项目根目录下创建一个migrations文件夹 。
flask db migrate:识别ORM模型的改变,生成迁移脚本
flask db upgrade:运行迁移脚本,同步到数据库中
ORM模型映射成表的三步都是在终端中输入命令。
Flask框架学习记录相关推荐
- Flask 框架学习_1
Flask 框架学习_1 Flask 框架 与 Django框架区别 Flask: 小巧.灵活,让程序员自己决定定制哪些功能,非常适用于小型网站. 对于普通的工人来说将毛坯房装修为城市综合体还是很麻烦 ...
- 【Python】flask框架学习 flask框架的基本使用
flask框架是什么? Flask 是一个轻量级的 Web 框架,用于构建 Web 应用程序.它基于 Python 编程语言和 Werkzeug 工具包,提供了简单易用的 API,可以轻松地创建 RE ...
- Flask框架学习整理——从零开始入门Flask
文章目录 Flask框架 一. 简介 二. 概要 三. 知识点(附代码) 1. Flask基础入门 1)路由route的创建: 2)endpoint的作用 3)request对象的使用 4)请求钩子b ...
- 谈谈Python的Flask框架学习与福利分享
在秋天中暑 熬过了炎炎夏日,却在这个初秋的日子中暑了.本来休息不好,今天又跑了一天,结果回来坐车吹空调冷热交替的崩溃了... 脑壳疼 回家就躺倒睡了一觉,感觉舒服点了,起床开电脑却又不知道学点什么,想 ...
- Python开发-flask框架学习
最近闲来无事,帮别人一起看看python3与flask,据说他想搞个登录注册的小demo,然后就给看了下,顺便简单的跟他说明了下.本文只是记录我在给别人讲解怎么使用python3与flask还有mon ...
- Python Flask框架学习
1.安装flask框架 在自己python的环境下直接通过pip安装,不写版本会默认最新版本,安装同时安装其他的库,属于flask的依赖包. pip install flask 2.快速使用flask ...
- Flask框架学习(持续更新)
文章目录 目录 文章目录 前言 一.Flask是什么 二.Flask基础 1.路由规则 2.Flask-Cors 解决跨域问题 3.Flask-Uploads 接受浏览器上传的文件 4.Flask蓝图 ...
- Scrapy框架学习记录
随着Python爬虫学习的深入,开始接触Scrapy框架 记录下两个参考教程: 官网教程:http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutor ...
- flask框架学习笔记
flask_day01 pycharm创建项目,连接到远程gitee仓库,创建仓库flask_study,分支helloworld, 自带第一个程序"helloworld",运行程 ...
最新文章
- valgrind——Cachegrind分析CPU的cache命中率、丢失率,用于进行代码优化。
- 最新的C#SqlHelper 类苏飞修改版(转载)
- orcle10忘记密码
- 前端学习(2613):action的方法
- c access mysql数据库_基于C#的Access MsSQL MySQL 三种数据库访问演示(含源文件Demo)...
- 大数据各组件环境完整安装
- Head First C 学习日志 第十章 进程间通信 输入输出重定向
- [2017.3.29]中国生育腚理不互质
- 使用fastjson读取超巨json文件引起的GC问题
- 在.NET外散步之我爱贪吃蛇Python -常见数据结构(新浪和百度云平台即将推出Python免费空间)...
- C/C++[算法入门]..
- windows下交换ctrl和capslock
- 鸟哥的Linux私房菜——第三部分|第19章 认识与分析日志文件
- E企云企业邮箱,选了不后悔
- Alien Skin X7PS调色滤镜插件下载及PS调色滤镜教程
- galaxy s8 android pc,三星S8/S8+发布!全面屏、智能助理、秒变PC,苹果8已败
- USB audio调试
- P5594 【XR-4】模拟赛
- 如何画出专业的原型图?(上)
- 解决移动硬盘可以识别,但不显示盘符的问题
热门文章
- dvorak键盘_如何在计算机或电话上切换到Dvorak(和其他键盘布局)
- 门店销售干货 | 4种不同类型的顾客VS销售技巧,直接套用!
- c语言题目 生日 星座 出生石,C语言 提示用户输入生日,根据用户生日求得此人属于哪个星座,输出该星座的名称....
- github desktop卡慢解决办法
- 基石为勤能补拙的迷宫之旅——第三天(Python基本数据类型,与用户交互(输出输入),运算符)
- ubuntu16.04安装GCC5.4
- java计算机毕业设计springboot+vue在线投票系统
- Excel打开后是空白页
- 安卓调用震动之Vibrator
- css选择器包含哪些,css选择器有哪些