赞
踩
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模式后
开启:
点击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)
主要作用:就是让其他电脑能访问到自己电脑上的flask项目
点击Edit Configurations… , 在Configuration下的Additional options中填写即可
--host=0.0.0.0 //可以写自己电脑的ip地址
// 0.0.0.0别人可以访问你电脑上的
点击Edit Configurations… , 在Configuration下的Additional options中填写
--host=0.0.0.0 --port=8000
url: http[80]/https[443]://www.xxx.com:443/path (冒号应为英文的:)
url与视图更准确来说是path与视图,只有path部分是需要自己现在编写的。
绝大部分网站都不可能只有首页一个页面,我们在制作网站的时候,需要定义许多不同的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的时候,需要携带一些参数过去。
比如获取博客详情,就需要把博客的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
在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_template
app = 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 = username
self.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 = username self.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+mystr
app.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") }}
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 = 22
return render_template("control.html",a = a)
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 = 22
persons = [{
"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的功能非常强大。
使用 Flask-SQLAlchemy操作数据库之前,要先创建一个由 Flask-SQLAlchemy提供的SQLAlchemy类的对象。在创建这个类的时候,要传入当前的app。然后还需要在app.config中设置SQLALCHEMY_ DATABASE_URI,来配置数据库的连接。
修改app.py
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = 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 here return 'Hello World!' if __name__ == '__main__': app.run()
对象关系映射(Object Relationship-Mapping),简称ORM,是一种可以用Python面向对象的方式来操作关系型数据库的技术,具有可以映射到数据库表能力的 Python类我们称之为ORM模型。一个ORM模型与数据库中一个表相对应,ORM模型中的每个类属性分别对应表的每个字段,ORM模型的每个实例对象对应表中每条记录。ORM技术提供了面向对象与SQL交互的桥梁,让开发者用面向对象的方式操作数据库,使用ORM模型具有以下优势。
修改app.py
from flask import Flask from flask_sqlalchemy import SQLAlchemy app = 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 here return '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模型创建一个对象,然后添加到会话中,再进行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"
关系型数据库一个强大的功能,就是多个表之间可以建立关系。
比如文章表中,通常需要保存作者数据,但是我们不需要直接把作者数据放到文章表中,而是通过外键引用用户表。这种强大的表关系,可以存储非常复杂的数据,并且可以让查询非常迅速。在 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!"
采用’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模型映射成表的三步都是在终端中输入命令。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。