Flask:轻量级python web框架
项目结构:
static文件夹,
templates文件夹,
app.py,其他python文件
导入
import flask #导入flask
使用flask
app = flask.Flask(__name__) #创建实例对象
@app.route('/',methods=["GET","POST"]) #设置路由
def index(): #定义路由函数
pass
if __name__ == "__main__":
app.run(debug = True)
flask项目配置
1.通过单行代码配置
app.config['JSON_AS_ASCII'] = True
2.通过配置文件配置
在config.py文件中配置,其中
JSON_AS_ASCII = True
主文件中获取配置信息
app.config.from_object(config) #从config.py中获取配置
将数据转化为json格式
jsoned_data = flask.jsonify(data) #可以将data转换为json格式
传参问题
@app.route("book/<int:id>")
或@app.route("/book?id=1")
def getbook(book_id):
pass
也可以通过函数获取地址栏中携带的参数
假如浏览器地址栏中:localhost:5000/getdata?id=2
@app.route("/getdata/")
def getdata():
book_id = flask.request.args.get("id") #获取到地址栏中传来的参数
print(book_id)#book_id = 2
pass
url反转
就是通过视图函数获取当前所指向的url:类似于获取当前网页目录
url1 = flask.url_for("视图函数名",参数 = 值...)
指定请求方法
@app.route("/book/detail/<int:id>",methods=['GET','POST'])
#通过methods参数指定请求方法
页面跳转和重定向
return flask.redirect(url) #通过redirect跳转到指定的url
使用jinja2模板
在templates文件夹中有index.html
视图函数中可以直接返回:
@app.route("/")
def index():
data= {"name":"张三","age":20}
return flask.render_template("index.html",data=data)
在index.html中使用携带来的变量需要jinja语法
{{ data.name }}
模板过滤器
@app.route("/")
def index():
data = {"name":"张三","age":20,"debt":-200000}
return flask.render_template("index.html",data=data)
index.html文件中:
name:{{data.name}}<br/>
name_length:{{data.name|length}}<br/>
debt:{{data.debt|abs}}<br/>
结果:
也可以给数组加过滤器:
a = ['a','b','c']
{{a | join("***")}} -> a***b***c
jinja模板之流程控制语句
{% for book in books %}
<div>{{book}}</div>
...
{% endfor %}
{% if a==10 %}
<div>a=10</div>
{% elif %}
...
{% endif %}
模板继承
通过{% block 块名 %}{% endblock %}和{% extends “父模板文件名.html” %}继承
base.html中设置一些通用页面
子模版中去继承父模板
浏览器中输入路由地址:
模板中加载静态文件
父模板中{% block 块名 %}{% endblock %}
子模版使用时:
{% block 块名 %}
<link rel = "stylesheet" herf = "{{url_for('static',filename='index.css')}}">
{% endblock %}
蓝图
创建一个blueprints文件夹
创建蓝图的文件
pl:books.py
import flask
bp = flask.Blueprint("Books",__name__,url_prefix= "/books")
@bp.route("/list")
def book_list():
return "图书列表"
app.py中:
from blueprints.books import bp as book_bp #导入蓝图
app = flask.Flask(__name__)
app.register_blueprint(book_bp) #注册蓝图
app.run()
在浏览器中输入localhost:5000/books/list
会出现 ”图书列表“
SQLAlchemy
一个独立的ORM框架,可以独立于flask存在,也可在其他项目中使用
Flask-SQLAlchemy:对SQLAlchemy的一个封装,能够更适合在flask中使用,使用前需要先安装
pip install flask-sqlalchemy
连接数据库
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'blog'
USERNAME = 'root'
PASSWORD = 'root'
DBURI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
app = flask.Flask(__name__)
db = flask_sqlalchemy.SQLAlchemy(app)
@app.route('/')
def index():#连接数据库
engine = db.get_engine()
conn = engine.Connect()
data = conn.execute("select * from users;").fetchall()
conn.close()
print(data)
return data
定义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 = True)
db.create_all() #用于创建表
@app.route("/article")
def add_article():
article = Article(title="hello",content="there is an apple")
db.session.add(article)
db.session.commit()
return "数据添加成功"
#查询数据
result = Article.query.filter_by(id=1)[0]
#修改
article.content = "It is modefied"
db.session.commit()
#删除数据
Article.query.filter_by(id=1).delete()
db.session.commit()
一对多关系:User和Article为一对多
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)
author_id = db.Column(db.Integer,db.ForeignKey("User.id"))#外键的类型和原数据中的类型必须一致
author = db.relationship("User",backref="articles")#backref表示可以通过User表访问article表
#用法
article = Article(title="loenly",content = "are you ok?")
user = User(username = "张三")
article.author = user
db.session.add(article)
db.session.commit()
一对一关系
user = db.relationship("User",backref=db.backref("extension",userlist = False)
#反向引用的时候,不是一个列表,而是一个对象,也就是限制数量来保证一对一
flask-migrate 数据迁移
pip install flask-migrate
python文件中:
import flask_migrate
db = flask_sqlalchemy.SQLAlchemy(app)
migrate = flask_migrate.Migrate(app.db)
命令行中去更新和迁移数据库
flask db init
flask db migrate
flask db upgrade
Flask中操作cookie和session
#Cookie
@app.route("/set_cookie")
def set_cookie():#设置cookie
response = flask.Response("设置cookie")
response.set_cookie("username","张三",max_age = 3600)
return response
@app.route("/get_cookie"):
username = flask.request.cookies.get("username")
print("用户名为:",username)
return "获取用户名成功"
#Session
#配置SECRET_KEY
app.config['SECRET_KEY'] = "hello222333"
@app.route('/set_session')
def set_session():#设置session
flask.session["age"] = 22
return "session设置成功"
@app.route("/get_session")
def get_session():
age = flask.session.get("age")
print("age = ",age)
return "获取session成功"
wtforms表单验证
pip install flask-wtf
如果要用到email验证器则需要安装
pip install email_validator
首先创建一个forms.py去写入表单验证器
import wtforms
from wtforms.validators import length,email
class LoginForm(wtform.Form):
email = wtforms.StringField(validator = [length(min=5,max = 20),email()])
password = wtforms.PasswordField(validators = [length(min=6,max = 18]))
在login.html中
<form action="/login" method = "post">
邮箱:<input type = "text" name = "email">
密码:<input type = "password" name = "password">
<input type = "submit" value = "登录">
</form>
app.py中:
import flask,forms
app = flask.Flask(__name__)
@app.route("/login")
def login():
if flask.request.method == "GET":
return flask.render_template("login.html")
else:
form = forms.LoginForm(flask.request.Form)
if form.vaidate():
return "格式正确"
else:
return "邮箱或密码格式错误"
加密werkzeug工具库
import werkzeug.security
password = "hello world"
hashed_password = werkzeug.security.generate_password_hash(password)
if werkzeug.security.check_password_hash(hashed_password,password):
print("密码正确")
制作随机验证码
string.digits 返回 ’0~9‘
string.ascii_letters 返回 'a~z A ~Z'
random.sample(样本,数量) 返回的是一个列表
#生成验证码
letters = string.digits+string.ascii_letters
verificationCode = "".join(random.sample(letters,6)) #随机生成一个6位的验证码
Flask发送邮件 flask-mail
config.py中配置邮箱,使用QQ邮箱
MAIL_SERVER = "smtp.qq.com"
MAIL_PORT = "465"
MAIL_USE_TLS = False
MAIL_USESSL = True
MAIL_DEBUG = True
MAIL_USERNAME = "XXXXXX@qq.com"
MAIL_PASSWORD = "XXXXXXXXXXXX" #需要在QQ邮箱中开启pop3/smtp服务
MAIL_DEFAULT_SENDER = "XXXXXX@qq.com" #发送者邮箱地址
app.py中
import flask,flask_mail,config
app = flask.Flask(__name__)
mail = flask_mail.Mail()
mail.init_app(app)
@app.route("/send_mail")
def send_mail():
message = flask_mail.Message(subject = "主题",recipients = ["XXXXX@qq.com"],body = "邮件内容")
mail.send(message = message)
return "邮件发送成功"
跨域问题解决
安装flask_cors
pip install flask_cors
import flask,flask_cors
app = flask.Flask(__name__)
flask_cors.CORS(app,resource = r"/*")
@app.route("/upload",methods = ["POST"])
def uploadfile():
result_text = {"code":200,"message":"1"}
response = flask.make_response(flask.jsonify(result_text)))
response.headers['Access-Control-Allow-Origin'] = "*"
response.headers["Access-Control-Allow-Methods"] = "OPTIONS,HEAD,GET,POST"
response.headers["Access-Control-Allow-Headers"] = 'x-requested-with'
return response
#返回的响应可以跨域