今天用Flask + MySQL 实现用户注册,登录和登出。
一、实战场景
Flask 框架实现用户的注册,登录和登出。
二、主要知识点
- flask_login 插件使用
- SQLAlchemy 基础操作
- 用户基础类设计
- Flask 读取配置文件
- 蓝图注册与使用
- wtforms 表单提交数据
- wtforms 表单验证
- Bootstrap 集成
- Jinjia2 模版继承
涉及的知识点和细节很多,我下面就直接贴出注册部分的核心代码。
三、核心代码
马上安排!
1、应用初始化 MySQL 和 flask_login 模块
\'\'\' Description: 创建应用程序,并注册相关蓝图 Python学习群 279199867 加群免费领取软件工具、视频教程、电子书、源码、课件,视频相关源码、福利文件赠送,学习问题交流共同进步! \'\'\' from flask import Flask from base.base_model import db from flask_login import LoginManager # 登录插件 login_manager = LoginManager() def register_auth_blueprint(app): # 注册蓝图 from app.auth import auth_bp app.register_blueprint(auth_bp) def create_app(config=None): # 创建应用 app = Flask(__name__) # 加载配置 app.config.from_object(\'config\') # 注册 SQLAlchemy db.init_app(app) # # 注册 login 模块 login_manager.init_app(app) # 未登录时候的默认跳转页面 login_manager.login_view = \'auth.login\' # # login_manager.login_message = \'请先登录或注册\' register_auth_blueprint(app) if config is not None: if isinstance(config, dict): app.config.update(config) elif config.endswith(\'.py\'): app.config.from_pyfile(config) return app app = create_app() with app.app_context(): db.create_all() if __name__ == \'__main__\': # 如果要使用 vscode 调试,需要将 debug 设置为 False,否则无法命中请求断点 app.run(host=\'0.0.0.0\', debug=True)
2、设置配置文件
APP_NAME = \"north\" SECRET_KEY = \"fNqh2TNw3l0Dj8ZCMQyQh7m1YvWVSgDx\" DEBUG = True SQLALCHEMY_DATABASE_URI = \'mysql://username:password@ip:3306/dbname\' # 设置sqlalchemy自动更跟踪数据库 SQLALCHEMY_TRACK_MODIFICATIONS = True # 查询时会显示原始SQL语句 SQLALCHEMY_ECHO = True
3、蓝图初始化
from flask import Blueprint auth_bp = Blueprint( \'auth\', __name__, ) from app.auth.user import user, auth
4、编写注册表单
<main class=\"form-signin w-100 m-auto\"> <form action=\"{{ url_for(\'auth.register\') }}\" method=\"post\"> <img class=\"mb-4\" src=\"{{ url_for(\'static\', filename=\"3rd/images/bootstrap-logo.svg\") }} \" alt=\"\" width=\"72\" height=\"57\"> <h1 class=\"h3 mb-3 fw-normal\">注册信息</h1> <div class=\"form-floating\"> <input class=\"form-control\" id=\"nickname\" name=\"nickname\" value=\"{{ form.data[\'nickname\'] | default(\'\',true) }}\" placeholder=\"昵称\"> <label for=\"floatingInput\">昵称</label> </div> <div class=\"form-floating\"> <input type=\"email\" class=\"form-control\" id=\"email\" name=\"email\" value=\"{{ form.data[\'email\'] | default(\'\',true) }}\" placeholder=\"Email\"> <label for=\"floatingInput\">邮箱</label> </div> <div class=\"form-floating\"> <input type=\"password\" class=\"form-control\" id=\"password\" name=\"password\" value=\"{{ form.data[\'password\'] | default(\'\',true) }}\" placeholder=\"Password\"> <label for=\"floatingPassword\">密码</label> </div> <div class=\"form-floating\"> <input type=\"password\" class=\"form-control\" id=\"confirm_password\" name=\"confirm_password\" value=\"{{ form.data[\'confirm_password\'] | default(\'\',true) }}\" placeholder=\"Confirm Password\"> <label for=\"floatingPassword\">确认密码</label> </div> {% if form and form.errors %} {% for key, error in form.errors.items() %} <div class=\"alert alert-warning\" role=\"alert\">{{ key }} : {{ error }}</div> {% endfor %} {% endif %} <button class=\"w-100 btn btn-lg btn-primary\" type=\"submit\">注册</button> <p class=\"mt-5 mb-3 text-muted\">秀儿 © 2017–2022</p> </form> </main>
5、提交注册表单
@auth_bp.route(\"/register\", methods=[\'POST\', \'GET\']) def register(): # 注册逻辑 form = RegisterForm(request.form) # 检查 if request.method == \'POST\' and form.validate(): # 执行正确逻辑 user = User() user.set_attrs(form.data) user.name = user.nickname user.token = user.generate_token() db.session.add(user) db.session.commit() # 执行登录 login_user(user, False) return redirect(url_for(\'auth.home\')) return render_template(\"auth/register.html\", form=form)
6、用户模型
import random from sqlalchemy import Column, ForeignKey, func from sqlalchemy import String, Unicode, DateTime, Boolean from sqlalchemy import TIMESTAMP, Integer, Float from flask_login import login_user, login_required, logout_user, current_user, UserMixin from werkzeug.security import generate_password_hash, check_password_hash from common.helpers.str_helper import random_string from north import login_manager from base.base_model import BaseModel class User(BaseModel, UserMixin): # UserMixin 继承属性 __tablename__ = \'users\' # 表基础值 phone_number = Column(String(16), unique=True) email = Column(String(64), unique=True, nullable=False) token = Column(String(64)) password = Column(\'password\', String(100)) status = Column(Integer, default=1) type = Column(Integer, default=1) # 定义一个对象属性,对应表中的 password 字段 _password = Column(\'password\', String(100)) @property def password(self): # 定义属性,使用对象属性赋值 return self._password @password.setter def password(self, raw): # 属性赋值 self._password = generate_password_hash(raw) def check_password(self, raw): # 检查密码 if not self._password: return False return check_password_hash(self._password, raw) def generate_token(self, expiration=60000): # 生成 token return random_string(32) @login_manager.user_loader def get_user(uid): # 必须, login 插件制定方法 return User.query.get(int(uid))
7、模型基类
import pymysql import datetime from flask_sqlalchemy import SQLAlchemy from sqlalchemy import Column, Integer, SmallInteger from sqlalchemy import String, Unicode, DateTime, Boolean # 初始化数据库类型 pymysql.install_as_MySQLdb() db = SQLAlchemy() # 模型基础类 class BaseModel(db.Model): __abstract__ = True id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) nickname = Column(String(32), nullable=False) is_enable = Column(SmallInteger, default=1, nullable=False) created_at = db.Column(db.DateTime, default=datetime.datetime.now) updated_at = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now) deleted_at = db.Column(db.DateTime) def __init__(self): pass # 字典赋值, 场景: 表单提交 def set_attrs(self, attrs): for key, value in attrs.items(): if hasattr(self, key) and key != \'id\': setattr(self, key, value)
8、表单验证
from wtforms import StringField, PasswordField, Form, validators # from wtforms.validators import Length, Email, \\ # ValidationError, EqualTo from app.auth.user.user_model import User class RegisterForm(Form): nickname = StringField(\'昵称\', validators = [ validators.DataRequired(), validators.Length(2, 32) # validators.Email(message=\'电子邮箱不符合规范\') ]) email = StringField(\'电子邮件\', validators = [ validators.DataRequired(), validators.Length(10, 50) # validators.Email(message=\'电子邮箱不符合规范\') ]) password = PasswordField(\'密码\', [ validators.DataRequired(), validators.EqualTo(\'confirm_password\', message=\'密码需要一致\') ]) confirm_password = PasswordField(\'Repeat Password\', [ validators.DataRequired(), ]) def validate_email(self, field): # 自定义验证,命名对应 if User.query.filter_by(email=field.data).first(): raise validators.ValidationError(\'邮件已被注册\') def validate_nickname(self, field): if User.query.filter_by(nickname=field.data).first(): raise validators.ValidationError(\'昵称已存在\')
9、代码主要目录结构
├── app
│ ├── __init__.py
│ ├── auth
│ │ ├── __init__.py
│ │ └── user
│ └── tools
│ ├── __init__.py
│ └── db_tools.py
├── base
│ ├── __init__.py
│ ├── base_blueprint.py
│ ├── base_form.py
│ └── base_model.py
├── common
│ ├── __init__.py
│ └── helpers
│ ├── __init__.py
│ └── str_helper.py
├── config.py
├── north.py
四、运行结果
1、注册和验证
2、注册成功登录
3、登录
兄弟们,今天的分享就到这里,下次见!
来源:https://www.cnblogs.com/hahaa/p/16470560.html
本站部分图文来源于网络,如有侵权请联系删除。