今天用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="https://www.cnblogs.com/{{ url_for('auth.register') }}" method="post">
- <img class="mb-4" src="https://www.cnblogs.com/{{ url_for('static', filename="3rd/images/bootstrap-logo.svg") }} " alt="" width="72" height="57">
- <h1 class="h3 mb-3 fw-normal">注册信息</h1>
-
-
- <input class="form-control"
- id="nickname" name="nickname"
- value="{{ form.data['nickname'] | default('',true) }}"
- placeholder="昵称">
- <label for="floatingInput">昵称</label>
-
-
- <input type="email" class="form-control"
- id="email" name="email"
- value="{{ form.data['email'] | default('',true) }}"
- placeholder="Email">
- <label for="floatingInput">邮箱</label>
-
-
- <input type="password" class="form-control"
- id="password" name="password"
- value="{{ form.data['password'] | default('',true) }}"
- placeholder="Password">
- <label for="floatingPassword">密码</label>
-
-
- <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>
-
- {% if form and form.errors %}
- {% for key, error in form.errors.items() %}
- {{ key }} : {{ error }}
- {% 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、登录

兄弟们,今天的分享就到这里,下次见!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |