flask框架

2023-10-28

一、flask简介

flask是一款非常流行的python web框架,它能流行的原因有以下几点:

1、微框架,简洁
2、flask和相应的插件写的很好
3、开发效率非常高,比如使用sqlalchemy操作的数据库可以节省开发者大量书写sql语句的时间

相较于django的优点:

django内置了非常完善和丰富的功能,如果想替换成自己想要的,要么不支持,要么非常麻烦。而flask的灵活度非常高,可以按照自己的意愿进行修改。

二、初体验

#从flask包中导入Flask对象
from flask import Flask
#使用Flask创建一个app对象,并且传递__name__参数
app = Flask(__name__)
#@app.route:设置访问的url,这里设置成一个根路径,用户访问了url的根路径就会执行hello_world函数,hello_world函数会执行hello world代码
@app.route('/')
def hello_world():
     return 'hello world'

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

三、flask配置

1、开启debug模式

场景:

如果我们对代码进行了修改,就得重新启动程序,重新加载url,比较麻烦,如果启用了debug模式,直接做代码的修改,不用在pycharm再重启代码,只需重新加载url即可

打开debug的方法:
在专业版只需要edit,勾选flask-debug按钮即可,社区版没有按钮,可以通过代码解决此问题,在调用时加上debug=True即可

......
if __name__ == "__main__":
    app.run(debug=True)

2、如何正确显示中文

以下代码为显示乱码的情况

from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
    return {"username":"李煜"}
if __name__ == "__main__":
    app.run(debug=True)

在这里插入图片描述
如何让其显示为正确的中文呢?需要修改配置文件,flask项目的配置都是通过app.config对象来进行配置的,显示中文乱码与JSON_AS_ASCII有关,默认为True,这里我们修改为False即可。

from flask import Flask
app = Flask(__name__)
app.config['JSON_AS_ASCII']=False
@app.route('/')
def index():
    return {"username":"李煜"}
if __name__ == "__main__":
    app.run(debug=True)

访问效果如下,在flask中,如果返回的数据是一个字典,则会自动变为json格式进行返回
在这里插入图片描述

2.1、 配置文件的优化

如果我们需要写的app.config配置过多,可以将所有的配置项都放在一个模块里,然后通过加载模块的方法进行配置。
我们将配置全部写在config文件里,config.py文件内容如下:

JSON_AS_ASCII=False

在程序文件里,我们进行加载模块

from flask import Flask
import config
app = Flask(__name__)
#以后所有的配置项,全部放在config.py中
app.config.from_object(config) #表示从哪个对象中加载配置,我们把配置写到了config文件里,这里写config即可
@app.route('/')
def index():
    return {"username":"李煜"}
if __name__ == "__main__":
    app.run(debug=True)

四、URL与视图

我们已经学到,一个url要与执行函数进行映射,使用的是@app.route装饰器。@app.route装饰器中,可以指定url的规则来进行更加详细的映射,比如现在要映射一个文章详情的url,文章详情的url是/book/id,id有可能为1,2,3

from flask import Flask
app = Flask(__name__)
import config
app.config.from_object(config)
books=[
    {"id":1,"name":"三国演义"},
    {"id":2,"name":"水浒传"},
    {"id":3,"name":"红楼梦"},
    {"id":4,"name":"西游记"},
]
@app.route("/book/<int:book_id>")
def book_list(book_id):
    for book in books:
        if book_id==book["id"]:
            return book
    return "id为{}的图书没有找到".format(book_id)

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

效果图如下:
在这里插入图片描述
在这里插入图片描述

1、构造URL(url-for)

一般我们通过一个URL可以执行到某一个函数,如果反过来,我们知道一个函数,怎么去获得这个url呢?url_for函数就可以帮助我们实现这个功能。
url_for函数的用法

url_for()函数接收两个及以上参数,接收函数名作为第一个参数,接收对应URL规则的命名参数,如果还出现其他的参数,则会添加到url的后面作为查询参数。

学习这个的目的是什么?

1、如果代码中涉及到了访问的url,但是url会根据需求经常变化,当代码中出现的Url过多,那我们去修改url是很麻烦的。
所以我们直接通过函数去反转得到url,这样不管url怎样变化,都会找到它
2、 url_for()函数会转义一些特殊字符和unicode字符串,这些事情url_for会自动的帮助我们搞定

from flask import Flask,url_for,jsonify
app = Flask(__name__)
import config
app.config.from_object(config)
books=[
    {"id":1,"name":"三国演义"},
    {"id":2,"name":"水浒传"},
    {"id":3,"name":"红楼梦"},
    {"id":4,"name":"西游记"},
]
@app.route("/book/<int:book_id>")
def book_detail(book_id):
    for book in books:
        if book_id==book["id"]:
            return book
    return "id为{}的图书没有找到".format(book_id)
@app.route("/book/list")
def book_list():
    for book in books:
        book["url"]=url_for("book_detail",book_id=book["id"])
    return jsonify(books)
if __name__ == '__main__':
    app.run(debug=True)

效果图如下:
在这里插入图片描述

五、指定HTTP方法

在@app.route()中可以传入一个关键字参数methods来指定本方法支持的HTTP方法。默认情况下,只能使用GET请求。

@app.route("/book/<int:book_id>",methods=["GET"])

GET请求和POST请求的区别:

如果只是从服务器上获取数据,一般都是GET请求
如果前端需要把数据发送给服务器,一般用POST请求

六、页面跳转和重定向

之前京东的网站为www.360buy.com这个网站,后面又新买了www.jd.com这个域名,如果老域名上还有客户访问,则需将老域名重定向在新域名上,访问的内容都是一样的。
重定向的分类:

永久性重定向的状态码是301,应用场景就是上述的京东实例;
临时性重定向的状态码是302,如果访问一个需要权限的网址,当前用户没有登录,应该重定向到登录页面。这种情况下,使用的是暂时性重定向。

from flask import Flask,redirect,url_for,request
app=Flask(__name__)
import config  #解决中文乱码问题
app.config.from_object(config)
@app.route("/profile")
def profile():
    user_id=request.args.get("id")
    if user_id:
        return "用户个人中心"
    else:
        return redirect(url_for("index"))
@app.route("/")
def index():
    return {"username":"李煜"}
if __name__ == '__main__':
    app.run(debug=True)

效果如下:
在这里插入图片描述
在这里插入图片描述

七、模板

模板是一个web开发必备的模块,因为在渲染一个网页的时候,并不是只渲染一个纯文本字符串,而是渲染一个富有文本标签的页面,这时候就需要使用模板了。
在Falsk中,配套的模板是Jinja2。

1、Falsk渲染Jinja模板

要渲染一个模板,通过render_template方法即可。

from flask import Flask,render_template
import config
app=Flask(__name__)
app.config.from_object(config)  #此为配置防止中文乱码的代码
@app.route('/about')
def about():
    return render_template("about.html")

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

about.html的内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>关于我们</title>
</head>
<body>
    <h1>我们是最棒的</h1>
</body>
</html>

访问效果图为:
在这里插入图片描述
访问流程:当访问/about的时候,about函数会在当前目录下的template文件夹下查找about.html模板文件
在这里插入图片描述

2、如何将python的变量传入到前端模板中

如果想要传递变量到模板中,可以把变量定义成字典,然后在render_template中,通过关键字参数的方式传递过去,render_template(“模板名称”,**context)

from flask import Flask,render_template
import config
app=Flask(__name__)
app.config.from_object(config)
@app.route('/about')
def about():
    context={
        "username":"李四"
    }
    return render_template("about.html",**context)

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

我们可以查看render_template的代码,我们看到图片这一块传入的参数为关键字参数,所以我们也应该写为关键字参数
在这里插入图片描述
在html页面中,我们应该如何修改呢?给要传的参数加上两个花括号即可,要传入的参数名就是python代码里的变量名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>关于我们</title>
</head>
<body>
    <h1>我们是最棒的。{{username}}</h1>
</body>
</html>

效果图如下:
在这里插入图片描述

3、Jinja2模板过滤器

过滤器就是通过管道符( | )进行使用的,例如{{name|length}}就会返回name的长度,过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。
例子:
不想让books以列表的形式展现,想要books以字符串的形式显示,每个项用逗号进行分割,可以使用join过滤器去处理

from flask import Flask,render_template
import config
app=Flask(__name__)
app.config.from_object(config)
@app.route('/about')
def about():
    context={
        "username":"lisi",
        "books":["红楼梦","西游记"]
    }
    return render_template("about.html",**context)

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

about.html页面的内容修改为下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>关于我们</title>
</head>
<body>
    <h1>我们是最棒的。{{username|length}}</h1>
    <h1>{{books}}</h1>
    <h1>{{books|join(",")}}</h1>
</body>
</html>

效果如下:
在这里插入图片描述

4、Jinja2中的控制语句

所有的控制语句都是放在{%…%}中,并且由{% endxx %}来进行结束,Jinja中常用的控制语句有if和for…in…
if举例:

from flask import Flask,render_template
import config
app=Flask(__name__)
app.config.from_object(config)
@app.route("/control")
def control():
    context={
        "age":17,
    }
    return render_template("control.html",**context)
if __name__ == '__main__':
    app.run(debug=True)

control.html页面的代码内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>控制语句</title>
</head>
<body>
{% if age > 18%}
    <div>您已成年!</div>
{% elif age < 18%}
    <div>您未成年!</div>
{% else %}
    <div>您刚成年!</div>
{% endif %}
</body>
</html>

效果如图:
在这里插入图片描述
for…in…举例

from flask import Flask,render_template
import config
app=Flask(__name__)
app.config.from_object(config)
@app.route("/control")
def control():
    context={
        "books":["红楼梦","西游记","水浒传","三国演义"]
    }
    return render_template("control.html",**context)
if __name__ == '__main__':
    app.run(debug=True)

control.html的代码内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>控制语句</title>
</head>
<body>
<ul>
{% for book in books %}
    <li>{{book}}</li>
{% endfor %}
</ul>
</body>
</html>

代码执行效果如下:
在这里插入图片描述
如果想要循环字典该怎么办?

...
def control():
    context={
        "person":{"name":"liyu","age":18}
    }
    return render_template("control.html",**context)
...

control.html的代码内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>控制语句</title>
</head>
<body>
{% for key,value in person.items() %}
    <div>{{key}}:{{value}}</div>
{% endfor %}
</body>
</html>

效果显示如下:
在这里插入图片描述

5、模板继承

Flask中的模板可以继承,通过继承可以把模板中许多重复出现的元素抽取出来,放在父模板中,并且父模板通过定义block给子模板开一个口,子模板根据需要,再实现这个block。
首先将各视图函数写好

from flask import Flask,render_template
import config
app=Flask(__name__)
app.config.from_object(config)
@app.route('/about')
def about():
    context={
        "username":"lisi",
        "books":["红楼梦","西游记"]
    }
    return render_template("about.html",**context)
    
@app.route("/control")
def control():
    context={
        "age":18
    }
    return render_template("control.html",**context)

@app.route("/")
def index():
    return render_template("index.html")
    
if __name__ == '__main__':
    app.run(debug=True)

代码中牵扯到3个子模板,我们将父模板规定为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="/control">控制页面</a>
    </li>
    <li>
        <a href="/about">关于我</a>
    </li>
</ul>
{% block body%}{% endblock %}
<footer style="background-color:#ccc">我是底部</footer>
</body>
</html>

其余的三个子模板代码如下:
index.html

{% extends "base.html" %}
{% block title %}
    知了传课首页
{% endblock %}

{% block body %}
    <h1>我是首页</h1>
{% endblock %}

control.html

{% extends "base.html" %}
{% block title %}
    控制
{% endblock %}

{% block body %}
{% if age > 18%}
    <div>您已成年!</div>
{% elif age < 18%}
    <div>您未成年!</div>
{% else %}
    <h1>您刚成年!</h1>
{% endif %}
{% endblock %}

about.html

{% extends "base.html" %}
{% block title %}
    关于我
{% endblock %}

{% block body %}
<h1>我们是知了。</h1>
{% endblock %}

访问效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

八、蓝图和子域名

之前我们写的url和视图函数都是处在同一个文件,如果项目比较大的话,这显然不是一个合理的结构,而蓝图可以帮助我们实现这种需求。功能是将项目模块划分

先写三个子模块,这三个文件全放在apps这个python packages里,结构如下:
在这里插入图片描述
book.py

from flask import Blueprint
#url_prefix就是设置url前缀
bp=Blueprint("book",__name__,url_prefix="/book")
@bp.route("/list")
def book_list():
    return "图书列表"

course.py

from flask import Blueprint
#url_prefix就是设置url前缀
bp=Blueprint("course",__name__,url_prefix="/course")
@bp.route("/list")
def course_list():
    return "课程列表"

user.py

from flask import Blueprint
#url_prefix就是设置url前缀
bp=Blueprint("user",__name__,url_prefix="/user")
@bp.route("/list")
def user_list():
    return "用户列表"

最后再写主代码

from flask import Flask
from apps.book import bp as book_bp
from apps.course import bp as course_bp
from apps.user import bp as user_bp
app=Flask(__name__)
app.register_blueprint(book_bp)
app.register_blueprint(course_bp)
app.register_blueprint(user_bp)

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

效果图如下,其余两个url访问也没有问题
在这里插入图片描述

九、MySQL数据库

在网站开发中,数据库是网站的重要组成部分,只有提供数据库,数据才能动态的展示,而不是在网页中显示一个静态的页面。MySQL由于不受平台限制,灵活度高被采用。因此在Falsk中,也使用MySQL来作为数据存储。
这里需要安装mysql及navicat,在官网下载即可。然后在navicat里连接Mysql就行了

1、SQLAlchemy介绍

SQLAlchemy是一个数据库的ORM框架,让我们操作数据库的时候不要再使用SQL语句了,跟直接操作模型一样,安装命令为pip install SQLAlchemy
SQLAlchemy与Flask-SQLAlchemy的区别:

SQLAlchmey:是一个独立的ORM框架,可以独立于Flask存在,也可以在其他项目中使用,比如django
Flask-SQLAlchemy:对SQLAlchemy的一个封装,更适合在flask中使用

flask-sqlalchemy连接数据库
事先在navicat里创建好数据库:ly_flask
在这里插入图片描述

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)

# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'ly_flask'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
@app.route('/')
def hello():
    '''写一个测试代码来验证是否连接成功'''
    engine = db.get_engine()
    # 连接
    with engine.connect() as conn:
        result = conn.execute("select 1")
        print(result.fetchone())
    return "hello!"

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

2、ORM模型-创建表及字段

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'ly_flask'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
#定义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)
#将ORM模型生成到数据库当中
db.create_all()
if __name__ == '__main__':
    app.run(debug=True)

上述代码的操作为:创建了名为article的表,并且添加了3个字段,效果如下:
在这里插入图片描述

3、增删改查操作

增加数据

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'ly_flask'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
#定义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)
#将ORM模型生成到数据库当中
db.create_all()
#做增删改查操作
@app.route("/article")
def article_view():
    #1、添加数据
    article=Article(title="钢铁是怎样炼成的",content="xxx")
    #将数据添加到数据库中
    db.session.add(article)
    #提交操作
    db.session.commit()
    return "数据添加成功"
if __name__ == '__main__':
    app.run(debug=True)

在浏览器查看
在这里插入图片描述
在navicat里查看数据是否添加成功
在这里插入图片描述
查询数据

......
@app.route("/article")
def article_view():
    #2、查询数据
    #filter_by:返回一个类列表的对象,第一个元素即是我们需要的数据
    article=Article.query.filter_by(id=1)[0]
    print(article.title)
    return "数据查询成功"
......

在这里插入图片描述
修改数据

......
@app.route("/article")
def article_view():
    # 3、修改数据
    # 在进行修改的时候,还要进行查询操作
    article = Article.query.filter_by(id=1)[0]
    article.content="yyy"
    db.session.commit()
    return "数据修改成功"
......

在navicat里查看content修改成功
在这里插入图片描述
删除数据

......
@app.route("/article")
def article_view():
    #4、删除数据
    Article.query.filter_by(id=1).delete()
    db.session.commit()
    return "数据删除成功"
......

在navicat里查看,数据已经被删除
在这里插入图片描述

4、外键

在MySQL中,外键可以让表之间的关系更加紧密,而SQLAlchemy同样也支持外键,通过ForeignKey类来实现,并且可以指定表的外键约束。
比如我们有article和user两张表,user表中的id是article表的外键,实现代码如下:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'ly_flask'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
#定义ORM模型
class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username=db.Column(db.String(200),nullable=False)
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)
    #添加外键,外键的数据类型一定要看所引用的字段的类型,上面user表的id字段写的整型,这里也写整型
    #db.ForeignKey("表名.字段名")
    author_id=db.Column(db.Integer,db.ForeignKey("user.id"))
    #外键是属于数据库底层的,不推荐直接在ORM中使用,所以要用到relationship
    # relationship:绑定外键的关系
    # #第一个参数是模型的名字,必须要和模型的名字保持一致
    # #backref="articles":代表反向引用,代表对方访问我的时候的字段名称
    author=db.relationship("User",backref="articles")

#将ORM模型生成到数据库当中
db.drop_all() 
 #因为我们之前已经创建过article表,而且有过各字段,
 #还没有讲到ORM数据库迁移的版本管理,所以我们先删除所有表,再进行创建
db.create_all()
if __name__ == '__main__':
    app.run(debug=True)

效果如下:
在这里插入图片描述
在这里插入图片描述

5、表关系

表之间的关系存在三种:一对一,一对多,多对多,而SQLAlchemy中的ORM也可以模拟这三种关系。一对一在SQLAlchemy中底层是通过一对多的方式模拟的。
一对多关系实现
一对多即一个作者可以发布多篇文章

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'ly_flask'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
#定义ORM模型
class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username=db.Column(db.String(200),nullable=False)
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)
    #添加外键,外键的数据类型一定要看所引用的字段的类型,上面user表的id字段写的整型,这里也写整型
    #db.ForeignKey("表名.字段名")
    author_id=db.Column(db.Integer,db.ForeignKey("user.id"))
    #外键是属于数据库底层的,不推荐直接在ORM中使用,所以要用到relationship
    # relationship:绑定外键的关系
    # #第一个参数是模型的名字,必须要和模型的名字保持一致
    # #backref="articles":代表反向引用,代表对方访问我的时候的字段名称
    author=db.relationship("User",backref="articles")

#将ORM模型生成到数据库当中
db.drop_all() 
db.create_all()
#一对多关系实现
@app.route("/otm")
def one_to_many():
    article=Article(title="111",content="xxx")
    user=User(username="liyu")
    article.author=user
    #已经把用户绑定在article的author上,所以只需要把article添加在数据库上面即可
    db.session.add(article)
    db.session.commit()
    return "one to many-数据操作成功"
if __name__ == '__main__':
    app.run(debug=True)

效果如下:
在这里插入图片描述
在这里插入图片描述
一对一实现
一对一即一个作者只能发布一篇文章
user和userextension之间的关系

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'ly_flask'
USERNAME = 'root'
PASSWORD = '123456'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
#定义ORM模型
class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username=db.Column(db.String(200),nullable=False)
class UserExtension(db.Model):
    __tablename__="user_extension"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    school=db.Column(db.String(100))
    user_id=db.Column(db.Integer,db.ForeignKey("user.id"))
    user= db.relationship("User", backref=db.backref("extension",uselist=False))

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)
    #添加外键,外键的数据类型一定要看所引用的字段的类型,上面user表的id字段写的整型,这里也写整型
    #db.ForeignKey("表名.字段名")
    author_id=db.Column(db.Integer,db.ForeignKey("user.id"))
    #外键是属于数据库底层的,不推荐直接在ORM中使用,所以要用到relationship
    # relationship:绑定外键的关系
    # #第一个参数是模型的名字,必须要和模型的名字保持一致
    # #backref="articles":代表反向引用,代表对方访问我的时候的字段名称
    author=db.relationship("User",backref="articles")

#将ORM模型生成到数据库当中
db.drop_all()
db.create_all()
@app.route("/oto")
def one_to_one():
    user=User(username="liyu")
    extension=UserExtension(school="清华大学")
    user.extension=extension
    db.session.add(user)
    db.session.commit()
    return "one to one成功"
if __name__ == '__main__':
    app.run(debug=True)

代码重点说明:

在UserExtension模型里,db.backref表示在反向引用的时候,如果需要传递一些其他的参数,那么就需要用到这个函数;否则不需要使用,只要在relationship的backref参数上,设置反向引用的名称就可以了;
uselist=False,代表反向引用的时候,不是一个列表,而是一个对象。

在这里插入图片描述
在这里插入图片描述

6、ORM模型迁移工具-Flask-Migrate插件

在实际的开发环境中,经常会发生数据库修改的行为。一般我们修改数据库不会直接手动去修改,而是去修改ORM对应的模型,然后再把模型映射到数据库中。这时候如果有一个工具能专门做这种事,就非常有用,而flask-migrate就是做这个事情的,flask-migrate是基于Alembic进行的一个封装,并集成到Flask中,而所有的迁移操作其实都是Alembic做的,它能跟踪模型的变化,并将变化映射到数据库中。
在pycharm里做如下操作:

flask db init   #只需要第一次执行,以后添加别的字段,直接执行以下两列命令
flask db migrate -m "xxxxxx"  #生成迁移脚本
flask db upgrade  #将迁移脚本映射在数据库中

在这里插入图片描述

十、cookie和session

cookie:在网站中,http请求是无状态的,第一次和服务器连接后并且登录成功后,第二次请求服务器依然不知道当前请求是哪个用户。cookie的出现就是为了解决这个问题,cookie会存放在浏览器当中。
session:存储在服务器中,session的出现是为了解决cookie存储不安全的问题。

flask中操作cookie和session

from flask import Flask,Response,request,session
app=Flask(__name__)
app.config["SECRET_KEY"]="123"

@app.route("/set_cookie")
def set_cookie():
    response=Response("cookie 设置")
    response.set_cookie("user_id","xxxx")
    return response

@app.route("/get_cookie")
def get_cookie():
    user_id=request.cookies.get("user_id")
    print("user_id",user_id)
    return "获取cookie"
@app.route("/set_session")
def set_session():
    session["username"]="liyu"
    return "session设置成功"

@app.route("/get_session")
def get_session():
    username=session.get("username")
    print("username",username)
    return "get_session"
if __name__ == '__main__':
    app.run(debug=True)

十一、Flask-WTF表单验证

表单验证的功能主要是为了验证用户提交数据的合法性。
Flask-WTF是简化了WTForms操作的一个第三方库,WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板,还包含其他功能:CSRF保护,文件上传等。

1、表单验证

app.py如下:

from flask import Flask,request,render_template
from forms import LoginForm
app=Flask(__name__)

@app.route("/login",methods=["GET","POST"])
def login():
    if request.method=="GET":
        return render_template("login.html")
    else:
        form=LoginForm(request.form)
        if form.validate():
            return "登录成功"
        else:
            return "邮箱或密码错误"
if __name__ == '__main__':
    app.run(debug=True)

可能会提示没有安装email_validators,直接在终端里pip install即可

forms.py如下:

import wtforms
from wtforms.validators import length,email
class LoginForm(wtforms.Form):
    email=wtforms.StringField(validators=[length(min=5,max=20),email()])
    password=wtforms.StringField(validators=[length(min=6,max=20)])

login.html如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/login" method="post">
    <table>
        <tbody>
        <tr>
            <td>邮箱:</td>
            <td>
                <input type="text" name="email">
            </td>
        </tr>
        <tr>
            <td>密码:</td>
            <td>
                <input type="text" name="password">
            </td>
        </tr>
        <tr>
            <td></td>
            <td><button>登录</button></td>
        </tr>
        </tbody>
    </table>
</form>
</body>
</html>

登录效果如下:
在这里插入图片描述
如果密码个数不够,则效果如下:
在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

flask框架 的相关文章

随机推荐

  • 2023全国大学生信息安全竞赛(ciscn)初赛题解

    战队信息 安全知识 甚至不用看视频 百度就有答案 除了那个最新的美国时政 其它的ChatGPT就能回答 Misc 签到卡 关注公众号 根据提示 直接print open flag read 国粹 脑洞题 给的题目原图有两排一模一样的麻将 思
  • Postman配置多环境请求地址

    作用 平时用postman测试接口时 同一个接口免不了要在多个环境测试 但是每次都要手动的修改请求的IP地址是在麻烦 可以用此方法提高效率 省事不少 1 创建 点击页面右上角齿轮 2 点击弹出页面右下角的Add按钮 3 填写请求地址 例如
  • 微分算子法个人整理

    陈文灯老师创立的微分算子法 在求解特定的微分方程能够省去大部分的计算时间 很久不写了 这篇为了回顾方便 一同有四种总结 感谢B站BV1D5411776Q的总结 考研加油 稳定发挥
  • [网络安全自学篇] 二十六.Shodan搜索引擎详解及Python命令行调用

    这是作者的系列网络安全自学教程 主要是关于网安工具和实践操作的在线笔记 特分享出来与博友共勉 希望您们喜欢 一起进步 前文分享了Web安全学习路线 并实现了最简单的木马和病毒代码 这篇文章将详细讲述Shodan搜索引擎的基本用法及Pytho
  • Jenkins+Python自动化测试之持续集成详细教程

    前言 今天呢笔者想和大家来聊聊Jenkins Python自动化测试持续集成 废话呢就不多说了哟咱们直接进入主题哟 一 Jenkins安装 Jenkins是一个开源的软件项目 是基于java开发的一种持续集成工具 用于监控持续重复的工作 旨
  • Oracle中如何导出存储过程、函数、包和触发器的定义语句?如何导出表的结构?如何导出索引的创建语句?...

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Oracle中如何导出存储过程 函数 包和触发器的定义语句 如何导出表的结构 如何导出索引的创建语句 QQ群里有人问 如何导出一个用户下的存储过程 麦苗答 方法有多种 可以
  • springboot整合eurake

    Spring Boot整合Eureka是一个比较常见的场景 Eureka是一个服务注册与发现中心 可以方便地管理服务的注册与发现 在整合过程中 需要在pom xml文件中添加对Eureka Server的依赖 并在Spring Boot应用
  • Vue.js 下的瀑布流组件 vue-waterfall

    vue waterfall 详细介绍 Vue js 下的瀑布流组件 ES5 ES6 UMD 兼容 享受数据驱动带来的便利 让事情变得简单
  • 判断t1树中是否有与t2树完全相同的子树

    描述 给定彼此独立的两棵二叉树 树上的节点值两两不同 判断 t1 树是否有与 t2 树完全相同的子树 示例1 输入 1 2 3 4 5 6 7 8 9 2 4 5 8 9 返回值 true 备注 1 n 500000 方法一 递归 要判断t
  • 使用echarts实现简单的关系图谱

    使用echarts实现简单的关系图谱 如图 代码
  • pytorch载入数据与对应的标签,使用torch.utils.data详解,DataLoader的使用

    在进行深度学习处理的时候 我们需要将数据输入到神经网络中进行训练 训练网络的学习能力 其实是根据一定的规则更新网络节点中的参数 而这个规则的来源就是依赖于数据与标签 我们需要将数据与标签相匹配 才能让网络进行训练 比如说网络学习到了一定的特
  • stem教育资源

    人生不同阶段都有不同的使命 在学生阶段 学习掌握知识为以后的人生获得成就的能力 就是这个阶段使命 为了这个使命 他们必须要学习忍耐 学会放弃 学会付出 这不仅仅是学习的需要 也是人生的一种修炼 纵观我们身边的人 但凡取得一定成就的都是要经过
  • 用 LangChain 构建基于资料库的问答机器人(三):ReAct

    大家好 我是 Jambo 我们已经学习了如何使用 LangChain 的一些基本功能 解下我们就应该要结合这些功能来做一些复杂的东西了 但在这之前 为了让同学们更好的理解 LangChain 在这其中做了什么 我想先介绍一下关于 GPT 使
  • 修改索引值python_pandas DataFrame的修改方法(值、列、索引)

    对于DataFrame的修改操作其实有很多 不单单是某个部分的值的修改 还有一些索引的修改 列名的修改 类型修改等等 我们仅选取部分进行介绍 一 值的修改 DataFrame的修改方法 其实前面介绍loc方法的时候介绍了一些 1 loc方法
  • STM32 IAP Ymodem

    STM32 IAP采用Ymodem协议升级固件 公司最近软件需要通过IAP来升级所有板卡的固件 其中板卡有2块 一块主控板卡 一块子控板卡 其中 主控板卡与子控板卡之间采用RS485通信 PC与主控板卡采用RS232通信 具体框架 一 PC
  • pc817光耦参数_光耦在电子电路中有什么作用?关键参数有哪些?一起了解一下...

    光耦作为一个可以对信号进行电气隔离的电子元器件 常用于开关电源电压反馈隔离 电路隔离控制 光耦在电子电路中有不可或缺的地位 了解光偶的特性对学习电子电路有不少帮助 开关电源电压反馈 光耦隔离控制继电器 今天就一起来了解一下光耦吧 电子元器件
  • linkstack头文件 c语言,链式栈的基本操作——LinkStack(C语言版)

    include stdafx h include define OK 1 define ERROR 0 define TRUE 1 define FALSE 0 define MAXSIZE 20 存储空间初始分配量 typedef int
  • odoo10源码win系统开发环境安装图文教程

    前言 odoo10的源码安装教程不太完整或对新手不够友好 本新手再次整合出一份友好的新手教程 老鸟慎入 准备工作 一个干净的window系统 事先没有其他python环境的系统 如果怕系统污染可以先用虚拟机安装熟悉了再正式安装 亲测wind
  • 【论文写作】——设置中英文字体

    打开文件 点击选项 选择高级 取消中文字体也应用于西文的勾选 然后选中全文 设置中文字体为宋体 设置英文字体为times new Roman
  • flask框架

    flask框架 一 flask简介 二 初体验 三 flask配置 1 开启debug模式 2 如何正确显示中文 2 1 配置文件的优化 四 URL与视图 1 构造URL url for 五 指定HTTP方法 六 页面跳转和重定向 七 模板