【Python】Flask + MySQL 实现用户注册,登录和登出

一给  金牌会员 | 2022-8-26 00:23:08 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 860|帖子 860|积分 2580

今天用Flask + MySQL 实现用户注册,登录和登出。
一、实战场景
Flask 框架实现用户的注册,登录和登出。
二、主要知识点

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

2、注册成功登录

3、登录

兄弟们,今天的分享就到这里,下次见!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

一给

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表