flask01
1、第一个flask文件
from flask import Flask
#使用flask类创建一个app对象
#__name__: 代表当前app.py这个模块
# 1.以后出现bug,可以快速定位
# 2. 对于寻找模板文件,有一个相对路径
app = Flask(__name__)
#创建一个路由和视图函数的映射
#http://www.baidu.com
@app.route('/')
def hello_world(): # put application's code here
return 'Hello haha哈!'
#1.dubug 模式
#直接刷新,无需重启服务器,如果开发时出现bug,在浏览器上就能看见出错信息
#2.修改host
#让其他电脑能访问到我电脑上的flask项目
#3.修改端口号
#防止端口占用,可以通过修改port监听其他端口
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')
2、URL与视图映射
from flask import Flask,request
app = Flask(__name__)
# URL参数可以指定类型个性化定制String,int,float,path……
@app.route('/blog/<int:blog_id>')
def blog_detail(blog_id):
return "您访问的博客是:%s" % blog_id
# /book/list:会给我返回第一页的数据
# /book/list?page=2: 获取第二页的数据
@app.route('/list')
def book_list():
# arguments:参数
#request.args:类字典类型
page = request.args.get('page',default = 1,type=int)
return f"您获取的是第{page}的图书列表!"
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')
3、jinja2模板渲染
Jinja2 是一种现代的、设计优雅的模板引擎,它是 Python 的一部分,由 Armin Ronacher 开发。Jinja2 允许你在 HTML 文档中嵌入 Python 代码,以及使用变量、控制结构和过滤器来动态生成内容。它的语法简洁清晰,易于学习和使用。
(1)模版传递参数
# app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
# 定义要传递给模板的参数
user = {'username': 'John', 'age': 30}
fruits = ['Apple', 'Banana', 'Orange', 'Mango']
return render_template('index.html', user=user, fruits=fruits)
if __name__ == '__main__':
app.run(debug=True)
<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<title>Flask Template Example with Parameters</title>
</head>
<body>
<h1>Hello, {{ user.username }}!</h1>
<p>You are {{ user.age }} years old.</p>
<h2>Favorite Fruits:</h2>
<ul>
{% for fruit in fruits %}
<li>{{ fruit }}</li>
{% endfor %}
</ul>
</body>
</html>
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
# 定义要传递给模板的参数
data = {
'user': {'username': 'John', 'age': 30},
'fruits': ['Apple', 'Banana', 'Orange', 'Mango']
}
return render_template('index.html', **data) # 这里使用**进行解包,这是Python3的特性
if __name__ == '__main__':
app.run(debug=True)
class User:
def __init__(self,username,email):
self.username =username
self.email = email
@app.route('/<blog_id>')
def blog(blog_id):
user = User(username='leican', email='123456@com')
return render_template("index.html",blog_id = blog_id,user=user)
(2)使用url_for 参数
# app.py
from flask import Flask, render_template, url_for
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/h')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<title>Flask Template Example with url_for()</title>
</head>
<body>
<h1>Hello, Flask!</h1>
<p>This is a template example.</p>
<p><a href="{{ url_for('hello') }}">Say Hello</a></p>
</body>
</html>
(3) include模板导入
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>include</title>
</head>
<body>
<div class="container">
{% include 'header.html' %}
<h4>主题内容</h4>
{% include 'footer.html' %}
</div>
</body>
</html>
(4) 使用静态资源
一旦你有了静态资源文件夹,你可以在模板中通过使用 url_for 函数来引用这些静态资源。例如,在模板中引用样式表文件 style.css:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Flask App</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<h1>Welcome to My Flask App</h1>
<img src="{{ url_for('static', filename='img/logo.png') }}" alt="Logo">
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
</body>
</html>
在这个示例中,url_for('static', filename='path/to/resource') 函数用于生成静态资源的 URL。在调用时,第一个参数 'static' 是 Flask 中默认用于静态资源的端点,而第二个参数 'filename' 是静态资源的路径。
可调整静态文件位置
app = Flask(__name__, static_folder="static2") # 设置静态文件夹地址为 static2
# 第二种方式 app.static_folder = 'static2'
4.jinja2语法
Jinja2 是一种现代的、设计优雅的模板引擎,它为开发者提供了一种简单而强大的方式来创建动态内容。Jinja2 的语法清晰简洁,易于学习和使用。在这里,我将详细介绍 Jinja2 的主要语法元素:
(1) 定义变量
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask Template Example</title>
</head>
<body>
{% set title = "Title" %}
{% with subtitle="subtitle" %}
{% set combined_title = title + " " + subtitle %}
<h1>{{ combined_title }}</h1>
{% with paragraph="This is the paragraph content of my website." %}
<p>{{ paragraph }}</p>
{% endwith %}
{% endwith %}
<!-- 此处出了with的范围则不可使用其中变量subtitle等 -->
</body>
</html>
with只在范围内可用, set则是全局, with和 set可以结合使用
(2)流程控制
Jinja2 支持常见的控制结构,如条件语句和循环。控制结构使用 {% ... %} 包裹
# app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
# 假设这是从后端传递给前端的数据
user = {'username': 'Alice', 'age': 30}
return render_template('index.html', user=user)
if __name__ == '__main__':
app.run(debug=True)
<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<title>选择结构示例</title>
</head>
<body>
<h1>欢迎访问我的网站!</h1>
<p>用户信息:</p>
<ul>
<li>用户名:{{ user.username }}</li>
<li>年龄:{{ user.age }}</li>
</ul>
{% if user.age < 18 %}
<p>您未满18岁,属于未成年人。</p>
{% elif user.age >= 18 and user.age < 60 %}
<p>您已满18岁,属于成年人。</p>
{% else %}
<p>您已年满60岁,属于老年人。</p>
{% endif %}
</body>
</html>
(3)过滤器
过滤器允许你在输出中应用转换。它们以管道符 | 的形式使用。
自定义过滤器
from flask import Flask,render_template,url_for
app = Flask(__name__)
# @app.template_filter("reverse") # 注册自定义过滤器
def reverse_filter(s): # 自定义过滤器函数
return s[::-1]
app.add_template_filter(reverse_filter,'dformat')
app.jinja_env.filters['reverse'] = reverse_filter # 注册自定义过滤器的第二种方法
# 路由
@app.route('/')
def index():
# 在模板中使用自定义过滤器
message = "Hello, World!"
some = [1,3,"哈哈",9,"唯一",True]
return render_template('index.html', message=message,some=some)
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title >LC首页</title>
</head>
<body style="color: aqua">
首页
{{ message }}
<hr>
{{ some|reverse }}
<hr>
<h3>{{ message|dformat }}</h3>
</body>
</html>
使用装饰器或者 app.jinja_env.filters都可以设置过滤器
(4)定义宏
宏类似于函数,允许你定义可重用的代码块。注意宏没有返回值
from flask import Flask, render_template
app = Flask(__name__)
# 定义一个简单的宏,用于在模板中显示消息
@app.template_global()
def display_message(message):
return f"Message: {message}"
@app.route('/')
def index():
return render_template('index.html', message="Hello, world!")
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask Template Example</title>
</head>
<body>
<!-- 使用宏显示消息 -->
{{ display_message(message) }}
</body>
</html>
5、 Flask连接MySQL
SQLAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLAlchemy操作的flask扩展。
SQLALchemy实际上是对数据库的抽象,让开发者不用直接和SQL语句打交道,而是通过Python对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.sql import text
app = Flask(__name__)
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'leican0605'
DATABASE = 'studentms'
app.config[
'SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4'
db = SQLAlchemy(app)
# app.app_context(): Flask 应用需要运行在 "应用上下文" 中才能访问配置和扩展(如 db)。with 语句确保上下文在代码块内有效。
with app.app_context():
# db.engine.connect(): 通过 SQLAlchemy 的数据库引擎(db.engine)创建一个新的数据库连接。
# with 语句确保连接在使用后自动关闭,避免资源泄漏。
with db.engine.connect() as conn:
# text('SELECT 1+10'): 将纯文本 SQL 语句包装成 SQLAlchemy 可执行的格式(防止 SQL 注入)。测试用的简单 SQL 查询,计算 1+10 的值
# conn.execute(): 执行 SQL 语句,返回一个结果集对象 rs(类型为 ResultProxy 或 CursorResult)。
rs: object = conn.execute(text('SELECT 1+10'))
print(rs.fetchone()) #从结果集中提取第一行数据(这里是 (11,),因为 1+10=11)。
@app.route('/')
def hello_world(): # put application's code here
return 'Hello World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
在Flask-SQLAlchemy中,插入、修改、删除操作,均由数据库会话管理。会话用db.session表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用commit()方法提交会话。
数据库会话是为了保证数据的一致性,避免因部分更新导致数据不一致。提交操作把会话对象全部写入数据库,如果写入过程发生错误,整个会话都会失效。
数据库会话也可以回滚,通过db.session.rollback()方法,实现会话提交数据前的状态。
在Flask-SQLAlchemy中,查询操作是通过query对象操作数据。最基本的查询是返回表中所有数据,可以通过过滤器进行更精确的数据库查询。
ORM模型
一个ORM模型与数据库中的一张表相对应,ORM模型的每个类的属性分别对应表的每个字段,ORM模型的每个实例化对象对应表中每条记录。ORM模型提供了面向对象与SQL交互的桥梁。
使用python创建数据库表
class student(db.Model):
__tablename__ = 'student'
id = db.Column(db.Integer,primary_key = True) #映射到表对象
name = db.Column(db.String(64),nullable=False)
password = db.Column(db.String(64),nullable=False)
def __repr__(self):
return f'<user {student.sname}'
with app.app_context():
db.create_all()
往数据库表中添加对象
@app.route('/add')
def add_student():
# 1、创建ORM对象
user1 = student(id = 1,name = "雷灿", password = "123")
user2 = student(id=2, name="pass", password="1230")
user3 = student(id=3, name="fazem", password="2025")
# 2、将ORM对象添加到db.Session中
db.session.add(user1)
db.session.add(user2)
db.session.add(user3)
# 3.将db.session中的改变同步到数据库中
db.session.commit()
return "用户添加成功"
# 插入一条数据
ro1 = Role(name='admin')
db.session.add(ro1)
db.session.commit()
#再次插入一条数据
ro2 = Role(name='user')
db.session.add(ro2)
db.session.commit()
us1 = User(name='wang',email='wang@163.com',pswd='123456',role_id=ro1.id)
us2 = User(name='zhang',email='zhang@189.com',pswd='201512',role_id=ro2.id)
us3 = User(name='chen',email='chen@126.com',pswd='987654',role_id=ro2.id)
us4 = User(name='zhou',email='zhou@163.com',pswd='456789',role_id=ro1.id)
db.session.add_all([us1,us2,us3,us4])
db.session.commit()
查询
@app.route('/query')
def query_student():
# 1.get查找:根据主键查找
student1 = student.query.get(2)
print(f"{student1.name} + {student1.password}")
# 2. filter_by查找 (Query对象)
students = student.query.filter_by(name = "雷灿")
for studentm in students:
print(f"{type(studentm)} ")
#3、 first()返回查询到的第一个对象,all()返回查询到的所有对象
student2 = student.query.first()
# 4、 filter模糊查询,返回名字结尾字符为g的所有数据。
students1 = student.query.filter(student.name.endswith('f')).all()
for student0 in students1:
print(f"{student0.name} ")
# 5、逻辑非,返回名字不等于wang的所有数据。
students2 = student.query.filter(student.name != '雷灿').all()
for student9 in students2:
print(f"{student9.name} ")
return "查找成功"
逻辑非,返回名字不等于wang的所有数据。
User.query.filter(User.name!='wang').all()逻辑与,需要导入and,返回and()条件满足的所有数据。
from sqlalchemy import and_
User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()逻辑或,需要导入or_
from sqlalchemy import or_
User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()
修改
# User.query.filter_by(name='zhang').update({'name':'li'})
@app.route('/update')
def update_student():
student1 =student.query.filter_by(name = "pass")[0]
student1.name = "LC"
db.session.commit()
return "数据修改成功"