今天用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.uj5u.com/houduan/498706.html
標籤:Python
下一篇:python基礎知識一
