Flask后端学习笔记

以学习代码为主,笔记在代码块的注释部分

1 基础语法

# 从flask这个包中导入Flask类
from flask import Flask

# 使用Flask类创建一个app对象
# __name__: 代表当前app.py这个模块
app = Flask(__name__)


# 创建一个路由和视图函数的映射
# '/'是根路由
@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.run()

2 URL与视图的映射

2.1 无参的url

# route是一个函数 一个装饰器 后面可以用来定义url里的path
# 这种是无参的url
@app.route('/')
def hello_world(): 
    return 'Hello World!'

2.2 含参的url

2.2.1 路径传参
# 带参数的url:将参数固定到了url中, 方式是路径传参
# 可以定义参数的类型 格式:<参数类型:参数名>
@app.route("/blog/<blog_id>")
def blog_detail(blog_id):
    return "您访问的博客是: %s" % blog_id
2.2.2 以查询字符串的方式传参
# 以查询字符串的方式传参,就不用在route那里写参数
# /book/list:返回第一页的数据
# /book/list?page=2:返回第二页的数据(用的是英文的?)
@app.route('/book/list')
def book_list():
    # arguments: 参数
    # request.args:类字典类型,可通过get取值,request是一个全局对象
    # get参数:key表示要查找的键,default表示默认值,type用来指定类型
    page = request.args.get("page", default=1, type=int)
    # 用f字符串,变量用花括号括住{}
    return f"您获取的是第{page}页图书列表"

3 Jinja2

3.1 模板渲染

# render_template是flask的一个函数,用于渲染模板
from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def hello_world():  
    # render_template里的参数就是你所要渲染的模板文件,
    # 默认从当前项目的template文件夹下寻找所写入的文件,然后读取并进行解析,再渲染成html代码,返回给浏览器。
    return render_template("index.html")

3.2 渲染变量

后端代码:

@app.route('/')
def hello_world():  
    user = User(username="abc", email="xx@qq.com")
    # 此处person字典类型
    person = {
        "username": "abc",
        "email": "xx@qq.com"
    }
    return render_template("index.html", person=person)

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--用“对象.属性名”的格式可以只引用对象的某个属性-->
<!--引用字典对象里的某个属性用中括号,也可以用“对象.属性名”的方式(常用)引用-->
<div>{{ person['username'] }} / {{ person.email }}</div>
</body>
</html>

3.3 过滤器

3.3.1 Jinja内置过滤器

后端代码:

# 类对象,有多个属性
class User:
    def __init__(self, username, email):
        self.username = username
        self.email = email


# 通过过滤器对某个变量(需要被过滤的值)进行处理
@app.route('/filter')
def filter_demo():
    user = User(username="abc", email="xx@qq.com")
    return render_template("filter.html", user=user)

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>过滤器使用demo</title>
</head>
<body>
<!--用管道符号“|”来调用过滤器,对变量user进行处理,变量user即为定义过滤器时的“value”(此处length为jinja2的内置过滤器,返回value序列的长度)-->
<div>{{ user.username }}--{{ user.username|length }}</div>
</body>
</html>
3.3.2 自定义过滤器

后端代码:

from flask import Flask, render_template
from datetime import datetime

app = Flask(__name__)


# 自定义过滤器
# 首先定义一个函数,参数包括被过滤的值value和设定的格式format
# 然后调用该函数,则会返回格式化的时间
#(time.strftime是一个python函数,用于格式化时间,格式取决于参数format)
def datetime_format(value, format="%Y-%m-%d %H:%M"):
    return value.strftime(format)


# 利用函数add_template_filter()将函数定义为过滤器并命名
app.add_template_filter(datetime_format, "dformat")


@app.route('/filter')
def filter_demo():
    mytime = datetime.now()
    return render_template("filter.html", mytime=mytime)

if __name__ == '__main__':
    app.run()

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>过滤器使用demo</title>
</head>
<body>
<div>{{ mytime|dformat }}</div>
</body>
</html>

3.4 模板继承

网站中,会有许多网页的模块是重复的,比如顶部的导航栏。通过模板继承,可以把一些重复性的代码写在父模板中,子模板继承父模板后,再分别实现对应页面的代码。

父模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title> <!--子模版中需要重写的部分定义为block-->
</head>
<body>
<h1>父模板</h1>
<ul>
    <li><a href="#">首页</a></li>
    <li><a href="#">新闻</a></li>
</ul>
{% block body %}
{% endblock %}
<footer>这是底部的标签</footer>
</body>
</html>

子模版:

<!--子模版继承父模板的代码,因此不需要其他多余的,只需填写block的内容-->
<!--与父模板不同的地方,就使用block语法,先在父模板写好一个block,再在子模版填充block-->
{% extends "base.html" %} <!--extends语法加载父模板-->
{% block title %}
我是子模版的标题
{% endblock %}
{% block body %}
我是子模版的body
{% endblock %}

3.5 控制语句

模板中的控制语句与python中的控制语句类似,注意Jinja2的格式要求。

后端代码:

@app.route('/control')
def control_statement():
    age = 18
    books = [{
        "name": "沉默的大多数",
        "author": "王小波"
    }, {
        "name": "动物园",
        "author": "乙一"
    }, ]
    return render_template("control.html", age=age, books=books)

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>控制语句Demo</title>
</head>
<body>
<!--控制语句应放在一对{% %}中,且在控制语句结束后,应有相应的结束语句,即endif;for循环语句同理-->
{% if age>18 %}
    <div>您已满18岁!</div>
{% elif age==18 %}
    <div>您刚满18岁!</div>
{% else %}
    <div>您未满18岁!</div>
{% endif %}

<!--jinja2的for循环没有break语句-->
{% for book in books %}
    <div>图书名称:{{ book.name }}, 作者:{{ book.author }}</div>
{% endfor %}

</body>
</html>

3.6 加载静态文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    <script src="{{ url_for('static', filename='my.js') }}"></script>
</head>
<body>
<!--加载静态文件需要用url_for()函数,在img的路径src中不能直接写这个函数,会被当成字符串,要用双花括号引起来-->
<!--用url_for()函数调用静态文件,第一个参数都是static,第二个参数就是文件名,
如果是在static文件夹下的其他文件夹,那么还要写上前面的路径(其他文件夹名/文件名)-->
<img src="{{ url_for('static', filename = 'haechan.jpg' ) }}" alt="">
</body>
</html>

4 数据库

4.1 Flask连接MySQL数据库

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 = "*******"
# MySQL上创建的数据库名称
DATABASE = "database_learn"

# 在app.config中设置好连接数据库的信息
app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"

# 然后使用SQLAlchemy(app)创建一个db对象
# SQLAlchemy会自动读取app.config中连接数据库的信息
db = SQLAlchemy(app)

4.2 ORM模型与表的映射

ORM模型映射成表的三部曲,有什么改动之和同步到数据库时就执行以下命令:

1.flask db init(这一步只需要执行一次)

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

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

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)

HOSTNAME = "127.0.0.1"
PORT = 3306
USERNAME = "root"
PASSWORD = "*******"
DATABASE = "database_learn"

app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"

db = SQLAlchemy(app)

migrate = Migrate(app, db)


# 以下为创建一个ORM模型,(db.Model)一定要写
class User(db.Model):
    __tablename__ = "user"
    # db.Column()把id映射到表中,Integer表示整型,primary_key表示是表的主键,autoincrement表示每新加一条数据,id会自动加一
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # String表示是字符串类型,在数据库中会映射成varchar(变动的字符类型)类型,参数100表示指定的最大长度是100
    # nullable=False表示字段不能为空
    username = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(100))

# 创建一个User类的对象,相当于创建了一条数据
user1 = User(username="abc", password="1234")

# db.create_all()表示将表同步到数据库中,即ORM模型与表的映射,但局限性大,不好用
with app.app_context():
    db.create_all()

4.3 ORM模型的添加、查询、修改和删除操作

4.3.1 添加
# (表数据的)添加操作
@app.route('/user/add')
def add_user():
    # 1.创建ORM对象
    user = User(username='abc', password="1234")
    # 2.将ORM对象添加到db.session中
    db.session.add(user)
    # 3.将db.session中的改变同步到数据库中
    db.session.commit()
    return "用户创建成功!"
4.3.2 查询
# 查询操作
@app.route('/user/query')
def query_user():
    # 查找方法1.get查找,根据表的主键查找,一次查找一条数据
    user = User.query.get(1)
    print(f"{user.id:}: {user.username}-{user.password}")
    # 查找方法2.filter_by查找,可查找多条数据
    # 此处的users是一个Query,类数组对象,可进行相似的操作
    users = User.query.filter_by(username="abc")
    print(type(users))
    for user in users:
        print(user.username)
    return "数据查找成功!"
4.3.3 修改
# 修改操作
@app.route('/user/update')
def update_user():
    # 1.先查找到某条数据才能进行修改
    user = User.query.filter_by(username="abc").first()
    user.password = "123456"
    # 2.同步到数据库中
    db.session.commit()
    return "密码修改成功!"
4.3.4 删除
# 删除操作
@app.route('/user/delete')
def delete_user():
    # 1.同样需要先查找到数据再进行删除操作
    user = User.query.get(1)
    # 2.从db.session中删除
    db.session.delete(user)
    # 3.同步到数据库中
    db.session.commit()
    return "数据删除成功!"

4.4 ORM外键与表的关系

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)
    # 添加外键“作者”,类型与所引用的外键的id的类型一致,引用的是表“user”中的字段“id”
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
    # 通过db.relationship()将author属性与User模型建立联系,
    # 当访问author属性时,会自动根据表article中表user产生的外键,在表User中查找对应id的信息,再赋值给author
    # backref会自动给User模型添加一个articles的属性,用来获取文章列表
    author = db.relationship("User", backref="articles")


@app.route('/article/add')
def article_add():
    article1 = Article(title="Flask学习", content="Flaskxxxxxxxx")
    article1.author = User.query.get(2)
    article2 = Article(title="Flask学习加油", content="Flaskxxxxxxxxxxxxx")
    article2.author = User.query.get(2)
    # 添加到session中,添加多条使用add_all
    db.session.add_all([article1, article2])
    # 同步到数据库中
    db.session.commit()
    return "文章添加成功!"


# 根据作者查找文章
@app.route('/article/query')
def query_article():
    user2 = User.query.get(2)
    for article in user2.articles:
        print(article.title)
    return "文章查找成功!"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值