建立一个项目以后,须要在手动建立几个包(含有__init__.py文件的目录)和文件html
一、在主目录下建立配置文件:config.py前端
二、在主目录下建立扩展文件:exts.pypython
三、在主目录下建立管理文件(供在命令行使用):manage.pymysql
四、在主目录下建立app包,在app包下再建立cms包管理后台的文件sql
五、在cms包下建立views.py文件管理视图函数、models.py文件管理数据库模型、forms.py文件管理表单验证数据库
在配置文件下配置密钥、数据库链接等(配置文件的全部变量必须是所有大写)flask
主目录/config.py import os SECRET_KEY = os.urandom(24) DEBUG = True SQLALCHEMY_DATABASE_URI = "mysql://你的数据库用户名:用户密码@127.0.0.1:3306/数据库名称" SQLALCHEMY_TRACK_MODIFICATIONS = False
Flask框架封装了数据库的一些操做,将其置为扩展包falsk-sqlalchemy,只须要实例化SQLAlchemy对象浏览器
主目录/exts.py from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
在入口文件定义一个建立app的方法,供蓝图使用,这里说的蓝图就是app包下的包(模块).因为本篇博客实现的是后台登陆,即涉及表单验证,因此须要防止csrf注入攻击安全
主目录/app.py from flask import Flask from flask_wtf import CSRFProtect from apps.cms import bp as cms_bp from apps.cms import login_manager as cms_login_manager import config from exts import db def create_app(): """ 主入口文件建立app,供其余蓝图使用 :return: 返回一个app """ app = Flask(__name__) # 防止csrf注入攻击 CSRFProtect(app) # 注册蓝图模块 app.register_blueprint(cms_bp, url_prefix="/cms") # 导入配置文件 app.config.from_object(config) # 数据库db初始化app db.init_app(app) # 后台登陆login_manager初始化app cms_login_manager.init_app(app) return app if __name__ == '__main__': app = create_app() app.run()
cms包下有一个初始化py文件,通常是用来供导包的session
主目录/app/cms/__init__.py from .views import bp from .views import login_manager
在蓝图中的模型文件中建立用户模型,即在cms包下的models.py文件建立。建立模型已做详细说明
主目录/app/cms/models.py from exts import db from datetime import datetime from werkzeug.security import generate_password_hash, check_password_hash from flask_login import UserMixin class CMSUser(db.Model, UserMixin): """ 定义一个类名,系统将类转换为表格,表名为cms_user 定义类的属性就是表格的字段名 为了安全性,能够将用户表的password属性置为保护属性如 _password 为了方便用户操做保护属性像操做普通属性同样,须要装饰 _password 在设置密码的过程当中,须要对密码加密——>调用generate_password_hash() 另外定义一个校验密码的方法check_password() 在校验密码的过程当中,须要对密码解密——>调用check_password_hash() """ __tablename__ = "cms_user" id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(50), nullable=False) _password = db.Column(db.String(100), nullable=False) email = db.Column(db.String(50), nullable=False, unique=True) join_time = db.Column(db.DateTime, default=datetime.now) def __init__(self, username, password, email): self.username = username self.password = password self.email = email @property def password(self): return self._password @password.setter def password(self, raw_password): """ 设置密码 :param raw_password: 前端后台传入的密码参数 :return:没有返回值 """ self._password = generate_password_hash(raw_password) def check_password(self, raw_password): """ 校验密码,将数据库的存入的密码解密以后再与传入的密码参数匹配 :param raw_password: 前端后台传入的密码参数 :return: True or False """ result = check_password_hash(self.password, raw_password) return result
Flask框架不像Django框架能够直接使用命令行生成迁移文件并同步到数据库当中,Flask框架须要借助flask_script包下的管理类Manager、flask_migrate包下的迁移类Migrate和一些相关的迁移命令类MigrateCommand。
一、先获取app对象
二、再实例化一个管理对象manage,绑定到app上
三、将app应用与db数据库对象绑定到迁移类中
四、将迁移文件中用到的命令封装成 db (这个db不是db数据库对象),调用add_command()添加到manage中
五、完成上面几个文件的代码填充,能够在命令行中输入相关命令,这里不作解释,代码中有提示
主目录/manage.py from flask_script import Manager from flask_migrate import Migrate, MigrateCommand from app import create_app from exts import db from apps.cms import models as cms_models # 获取模型中定义的类 CMSUser = cms_models.CMSUser app = create_app() # 定义Manager类实例化对象 manage = Manager(app) # 将app应用与db数据库绑定到迁移文件中 Migrate(app, db) # 将迁移文件用到的命令换成db开头(manage.py文件能够自定义命令)添加到manage中 manage.add_command("db", MigrateCommand) @manage.option("-u", "--username", dest="username") @manage.option("-p", "--password", dest="password") @manage.option("-e", "--email", dest="email") def create_cms_user(username, password, email): """ 自定义建立后台用户的命令,在cmd命令行中输入相似于以下命令,便可添加用户:(在虚拟环境下) python manage.py db create_cms_user -u 用户名 -p 密码 -e 邮箱地址 :param username: :param password: :param email: :return: 返回一提示消息 """ user = CMSUser(username=username, password=password, email=email) db.session.add(user) db.session.commit() print("cms用户添加成功") if __name__ == "__main__": manage.run()
对前端后台登陆的表单提供的数据进行验证,须要借助flask_wtf包下的FlaskForm类
主目录/app/cms/forms.py from flask_wtf import FlaskForm from wtforms import StringField, IntegerField from wtforms.validators import DataRequired, Length, Email class LoginForm(FlaskForm): email = StringField(validators=[DataRequired(message="请输入邮箱地址"), Email(message="请输入正确的邮箱格式")]) password = StringField(validators=[Length(6, 20, message="请输入正确格式的密码")]) remember = IntegerField()
这里没有设置页面,就不渲染页面,直接返回一个字符串标识一下便可。渲染页面作的事情通常是在views.py中实现的,这个views.py文件采用了两种方式:视图函数和基于调度方法的类视图。
这里有必要提一下:对于没有登陆的行为,是不能访问主页(这里是指登陆成功以后跳转的页面)。实现这一要求,咱们须要从flask_login包下导入login_user、logout_user、login_required、LoginManager
一、和上面同样,实例化LoginManager对象login_manager也要初始化app(在入口文件app.py会有一行代码)
二、对于没有登陆的用户咱们须要给一个重定向(咱们把它做为重定向)。这个实例化对象有一个属性login_view,给其赋值(值是一个url)
三、最重要的一点:调用了login_user()会自动生成一个session值,调用了logout_user()会自动删除这一个session值。这个session值是经过装饰器@login_manager.user_loader修饰的函数生成
四、视图函数和类视图已在代码中做详细说明
主目录/app/cms/views.py from flask import Blueprint, views, render_template, request, session, redirect, url_for from flask_login import login_required, LoginManager from flask_login import login_user from .forms import LoginForm from .models import CMSUser # 指定没有登陆时重定向的页面,须要将LoginManager的实例化对象初始化app(在入口文件中) login_manager = LoginManager() login_manager.login_view = "cms.login" # 定义蓝图对象 bp = Blueprint("cms", __name__) @bp.route("/") @login_required def index(): return "cms index" class LoginView(views.MethodView): """ get方法对应前端后台的get请求,主要是渲染页面 post方法对应前端后台的post请求: 一、先验证用户的输入是否符合表单验证的要求,若是不符合要求,则返回具体的错误 二、先经过邮箱查找用户并经过查找的用户密码与后台表格密码进行验证,若是没有找到,返回邮箱或者密码错误 三、匹配成功则经过login_user(user)自动保存session值 四、经过获取前端后台的remember值给session定义过时时间,默认是浏览器会话关闭 """ def get(self, message=None): return render_template("cms/cms_login.html", message=message) def post(self): form = LoginForm(request.form) if form.validate(): email = form.email.data password = form.password.data remember = form.remember.data user = CMSUser.query.filter(CMSUser.email == email).first() if user and user.check_password(password): # 自动生成一个session值 login_user(user) if remember: # 设置session的过时时间,默认为31天 session.permanent = True return redirect(url_for("cms.index")) return redirect(url_for("cms.index")) else: return self.get(message="邮箱或者密码错误") else: message = form.errors.popitem()[1][0] return self.get(message=message) bp.add_url_rule("/login", view_func=LoginView.as_view("login")) @login_manager.user_loader def load_user(user_id): """ 后台用户类必须继承UserMixin,以防用户表没有定义校验的字段,如:is_active等 :param user_id: :return: """ return CMSUser.query.get(user_id)
前台用当前登陆的用户的相关信息的几种方式:
一、能够在模板上(页面)使用当前登录用户的代理current_user(具体值就加“点属性”)
二、在views.py文件中将登陆的用户信息保存到 g 对象中(这个 g 对象很重要,并且使用很方便)
这样一个后台登陆实现已经实现了,能帮助到你们,点个赞,加个关注,诚挚感谢!