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)

一些过滤器

  1. abs(value):返回一个数值的绝对值,例如{{ -1|abs }}。如果给的参数类型不为数字,就会报错。

  2. default(value,default_value,boolean=False):如果value没有定义,则返回第二个参数default_value。如果想要让 value在被判断为False的情况下(传入'',[],None,{}这些值的时候)使用default_value,则应该将后面的boolean参数设置为True。

  3. escape(value):将一些特殊字符,比如:&,<,>,",'进行转义。因为Jinja2默认开启了全局转义,所以在大部分情况下无需手动使用这个过滤器去转义,只有在关闭转义的情况下会需要使用。

  4. first(value): 返回序列的第一个元素

    • 如果是一个字典,那么返回的是key的值
  5. last(value): 返回序列的最后一个元素

  6. format(value,*args,**kwargs): 格式化字符窜,和python中写法是一样的。

    {{ "%s/%s"|format("username","email") }}
    
  7. 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驱动包。

  1. MySQL-python:也就是 MySQLdb。是对C语言操作 MySQL数据库的一个简单封装。遵循了Python DB·API v2。但是只支持Python2。

  2. mysqIclient:是 MySQL-python的另外一个分支。支持Python3并且修复了一些bug,是目前为止执行效率最高的驱动,但是安装的时候容易因为环境问题出错。

  3. pymysql:纯 Python实现的一个驱动。因为是纯 Python编写的,因此执行效率不如 mysqlclient。也正因为是纯 Python写的,因此可以和Python代码无缝衔接。

  4. 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模型具有以下优势。

  1. 开发效率高:几乎不需要写原生SQL语句,使用纯 Python的方式操作数据库,大大的提高了开发效率。
  2. 安全性高:ORM模型底层代码对一些常见的安全问题,比如SQL注入做了防护,比直接使用SQL语句更加安全。
  3. 灵活性强: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模型映射成表的三步

  1. flask db init:创建迁移环境 ,迁移环境只需要创建一次。这会在你的项目根目录下创建一个migrations文件夹 。

  2. flask db migrate:识别ORM模型的改变,生成迁移脚本

  3. flask db upgrade:运行迁移脚本,同步到数据库中

ORM模型映射成表的三步都是在终端中输入命令。

Flask框架学习记录相关推荐

  1. Flask 框架学习_1

    Flask 框架学习_1 Flask 框架 与 Django框架区别 Flask: 小巧.灵活,让程序员自己决定定制哪些功能,非常适用于小型网站. 对于普通的工人来说将毛坯房装修为城市综合体还是很麻烦 ...

  2. 【Python】flask框架学习 flask框架的基本使用

    flask框架是什么? Flask 是一个轻量级的 Web 框架,用于构建 Web 应用程序.它基于 Python 编程语言和 Werkzeug 工具包,提供了简单易用的 API,可以轻松地创建 RE ...

  3. Flask框架学习整理——从零开始入门Flask

    文章目录 Flask框架 一. 简介 二. 概要 三. 知识点(附代码) 1. Flask基础入门 1)路由route的创建: 2)endpoint的作用 3)request对象的使用 4)请求钩子b ...

  4. 谈谈Python的Flask框架学习与福利分享

    在秋天中暑 熬过了炎炎夏日,却在这个初秋的日子中暑了.本来休息不好,今天又跑了一天,结果回来坐车吹空调冷热交替的崩溃了... 脑壳疼 回家就躺倒睡了一觉,感觉舒服点了,起床开电脑却又不知道学点什么,想 ...

  5. Python开发-flask框架学习

    最近闲来无事,帮别人一起看看python3与flask,据说他想搞个登录注册的小demo,然后就给看了下,顺便简单的跟他说明了下.本文只是记录我在给别人讲解怎么使用python3与flask还有mon ...

  6. Python Flask框架学习

    1.安装flask框架 在自己python的环境下直接通过pip安装,不写版本会默认最新版本,安装同时安装其他的库,属于flask的依赖包. pip install flask 2.快速使用flask ...

  7. Flask框架学习(持续更新)

    文章目录 目录 文章目录 前言 一.Flask是什么 二.Flask基础 1.路由规则 2.Flask-Cors 解决跨域问题 3.Flask-Uploads 接受浏览器上传的文件 4.Flask蓝图 ...

  8. Scrapy框架学习记录

    随着Python爬虫学习的深入,开始接触Scrapy框架 记录下两个参考教程: 官网教程:http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutor ...

  9. flask框架学习笔记

    flask_day01 pycharm创建项目,连接到远程gitee仓库,创建仓库flask_study,分支helloworld, 自带第一个程序"helloworld",运行程 ...

最新文章

  1. valgrind——Cachegrind分析CPU的cache命中率、丢失率,用于进行代码优化。
  2. 最新的C#SqlHelper 类苏飞修改版(转载)
  3. orcle10忘记密码
  4. 前端学习(2613):action的方法
  5. c access mysql数据库_基于C#的Access MsSQL MySQL 三种数据库访问演示(含源文件Demo)...
  6. 大数据各组件环境完整安装
  7. Head First C 学习日志 第十章 进程间通信 输入输出重定向
  8. [2017.3.29]中国生育腚理不互质
  9. 使用fastjson读取超巨json文件引起的GC问题
  10. 在.NET外散步之我爱贪吃蛇Python -常见数据结构(新浪和百度云平台即将推出Python免费空间)...
  11. C/C++[算法入门]..
  12. windows下交换ctrl和capslock
  13. 鸟哥的Linux私房菜——第三部分|第19章 认识与分析日志文件
  14. E企云企业邮箱,选了不后悔
  15. Alien Skin X7PS调色滤镜插件下载及PS调色滤镜教程
  16. galaxy s8 android pc,三星S8/S8+发布!全面屏、智能助理、秒变PC,苹果8已败
  17. USB audio调试
  18. P5594 【XR-4】模拟赛
  19. 如何画出专业的原型图?(上)
  20. 解决移动硬盘可以识别,但不显示盘符的问题

热门文章

  1. dvorak键盘_如何在计算机或电话上切换到Dvorak(和其他键盘布局)
  2. 门店销售干货 | 4种不同类型的顾客VS销售技巧,直接套用!
  3. c语言题目 生日 星座 出生石,C语言 提示用户输入生日,根据用户生日求得此人属于哪个星座,输出该星座的名称....
  4. github desktop卡慢解决办法
  5. 基石为勤能补拙的迷宫之旅——第三天(Python基本数据类型,与用户交互(输出输入),运算符)
  6. ubuntu16.04安装GCC5.4
  7. java计算机毕业设计springboot+vue在线投票系统
  8. Excel打开后是空白页
  9. 安卓调用震动之Vibrator
  10. css选择器包含哪些,css选择器有哪些