Flask部分:
app.py文件:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world(): # put application's code here
return 'Hello world!'
if __name__ == '__main__':
app.run(debug=True)
SQLAlchemy部分:
pip install flask_sqlalchemy
2 初始化SQLAlchemy对象
from flask_sqlalchemy import SQLAlchemy
HOSTNAME = '127.0.0.1'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
# mysql创建的数据库名称
DATABASE = 'xxxx'
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
db = SQLAlchemy(app)
Migrate部分
pip install flask-migrate
2.初始化migrate对象
from flask-migrate import Migrate
migrate = Migrate(app, db)
- ORM映射生成三步:
- flask db init 只需要执行一次
- flask db migrate 识别orm对象的改变,生成迁移脚本
- flask db upgrade 运行迁移脚本,同步到数据库中
config配置
app.py中
import config
app.config.from_object(config)
#替换在app.py中config配置如:app.config['SQLALCHEMY_DATABASE_URI'] = ''
解决循环导入问题:
生成exts.py
#解决循环导入的问题
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
app.py中修改:
from exts import db
from models import User
db.init_app(app)
models.py中
from exts import db
flask-mail使用
使用时,需要个人邮箱或者企业邮箱设置中找到POP3/SMTP服务点击开启,会有一个授权码。
pip install flask-mail
#exts文件中写入:
from flask-mail import Mail
mail = Mail()
#app.py中引入:
from exts import mail
mail.init_app(app)
#邮箱服务器配置
#config文件中写入
MAIL_SERVER = "smtp.qq.com"
MAIL_USE_SSL = True
MAIL_PORT = 465
MAIL_USERNAME = "邮箱账号"
MAIL_PASSWORD = "开启SMTP服务时生成的授权码"
MAIL_DEFAULT_SENDER = "邮箱账号"
from flask_mail import Message
# sender:邮件的发件人地址。默认值为 None,需要在 Flask 应用程序配置中定。
# recipients:邮件的收件人地址,可以是字符串类型或列表类型。
# subject:邮件的主题,字符串类型。
# body:邮件的正文内容,字符串类型。
# cc:邮件的抄送地址,可以是字符串类型或列表类型。
# bcc:邮件的秘密抄送地址,可以是字符串类型或列表类型。
# html:邮件的 HTML 格式内容,字符串类型。
# charset:邮件的编码格式,默认为 utf-8。
# attachments:邮件的附件列表,每个附件是一个元组,包含附件名和附件内容。
message = Message(subject="邮箱测试", recipients="xxx@qq.com", body="这是一条测试邮件")
mail.send(message)
邮箱验证码
ORM模型使用
user = User(username="xx", .....)
db.session.add(user)
db.session.commit
表单验证
flask-wtf
pip install flask-wtf
pip install email_validator #邮箱验证需要
使用
import wtforms
from wtforms.validators import Email, EqualTo, Length
from models import User
class RegisterForm(wtforms.Form):
email = wtforms.StringField(validators=[Email("邮箱格式错误")])
captcha = wtforms.StringField(validators=[Length(min=6, max=6, message="验证码格式错误")])
username = wtforms.StringField(validators=[Length(min=4, max=20, message="用户名格式错误")])
password = wtforms.StringField(validators=[Length(min=4, max=20, message="密码格式错误")])
confirm = wtforms.StringField(validators=[EqualTo("password", message="两次密码不一致")])
#自定义判断:
# 验证用户名是否唯一
def validate_username(self, field):
# 想要获取其他信息:使用self.xxx,如self.email
username = field.data
user = User.query.filter_by(username=username).first()
if user:
raise wtforms.ValidationError(message="用户名已存在")
app.py中调用:
image.png
用户的密码加密:
from werkzeug.security import generate_password_hash, check_password_hash
#加密存库:
user = User(username=username, password=generate_password_hash(password), email=email)
#判断密码是否一致
generate_password_hash(password), email=email)
#登录实现
@bp.route('/login')
def login():
if request.method == 'GET':
return render_template('login.html')
else:
form = LoginForm(request.form)
if form.validate():
username = form.username.data
password = form.password.data
user = User.query.filter_by(username=username).first()
if user:
is_pass = check_password_hash(user.password, password)
# 用户名密码验证成功
if is_pass:
# cookie中不适合放太多数据,适合存储登录授权相关的信息
# flask中的session是通过加密后存储在cookie中的
# session使用时需要加密,需在config中配置SECRET_KEY='',设置一个长度大概为20位左右的随机字符,
session['user_id'] = user.id
redirect(url_for('index'))
#用户名密码验证失败
else:
return redirect(url_for('auth.login'))
else:
#用户没有注册
return redirect(url_for('auth.register'))
else:
# 用户名密码验证失败
print(form.errors)
return redirect(url_for('auth.login'))
获取session中存储的用户信息
# 在每个请求之前注册一个要运行的函数,每一次请求都会执行一次。
@app.before_request
def my_before_request():
user_id = session.get("user_id")
if user_id:
user = User.query.get(user_id)
setattr(g, "user", user)
else:
setattr(g, "user", None)
#context_processor上下文处理器,返回的字典可以在全部的模板中使用。
@app.context_processor
def my_context_processor():
return {"user": g.user}
钩子函数
- @before_first_request在对应用程序实例的第一个请求之前注册要运行的函数,只会运行一次。
- @before_request在每个请求之前注册一个要运行的函数,每一次请求都会执行一次。
- @after_request在每个请求之后注册一个要运行的函数,每次请求完成后都会执行。需要接收一个 Response 对象作为参数,并返回一个新的 Response 对象,或者返回接收的 Response 对象。
- @teardown_request注册在每一个请求的末尾,不管是否有异常,每次请求的最后都会执行。
- @context_processor上下文处理器,返回的字典可以在全部的模板中使用。
- @template_filter('upper')增加模板过滤器,可以在模板中使用该函数,后面的参数是名称,在模板中用到。
- @errorhandler(400)发生一些异常时,比如404,500,或者抛出异常(Exception)之类的,就会自动调用该钩子函数。
- @teardown_appcontext不管是否有异常,注册的函数都会在每次请求之后执行。
网友评论