zoukankan      html  css  js  c++  java
  • (五)flask搭建博客系列之LoginManager

    本篇博客主要介绍 flask-login 会话管理方面的内容,完成用户合法的登录和登出,以及一些页面视图的保护功能。

    1.相关库安装

    pip install flask-login
    

    2.相关代码

    在 extensions.py 中添加 flask-login 的扩展实例和其需要的加载用户函数,以及相关的登录控制:

    from flask_sqlalchemy import SQLAlchemy
    from flask_migrate import Migrate
    from flask_bootstrap import Bootstrap
    from flask_login import LoginManager
    
    
    db = SQLAlchemy()
    migrate = Migrate()
    bootstrap = Bootstrap()
    login_manager = LoginManager()
    
    
    @login_manager.user_loader
    def load_user(user_id):
        from myblog.models import Admin
        user = Admin.query.get(int(user_id))
        return user
    
    
    login_manager.login_view = 'admin.login'
    login_manager.login_message = '你必须登陆后才能访问该页面!'
    login_manager.login_message_category = "info"
    

    在 __init__.py 中添加初始化 flask-login 的代码:

    from flask import Flask
    
    from myblog.home.blog import blog_bp
    from myblog.home.admin import admin_bp
    from myblog.extensions import db, migrate, bootstrap, login_manager
    from myblog.config import Config
    
    
    def create_app():
        app = Flask(__name__)
        app.config.from_object(Config)
    
        register_blueprints(app)
        register_extensions(app)
    
        return app
    
    
    def register_blueprints(app):
        app.register_blueprint(blog_bp)
        app.register_blueprint(admin_bp, url_prefix='/admin')
    
    
    def register_extensions(app):
        db.init_app(app)
        db.create_all(app=app)
        migrate.init_app(app, db)
        bootstrap.init_app(app)
        login_manager.init_app(app)
    

    修改 models.py 中的 Admin 类,使其继承自 UserMixin 类:

    from datetime import datetime
    from werkzeug.security import generate_password_hash, check_password_hash
    from flask_login import UserMixin
    
    from myblog.extensions import db
    
    
    class Admin(db.Model, UserMixin):
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(20))
        password_hash = db.Column(db.String(128))
    
        def set_password(self, password):
            self.password_hash = generate_password_hash(password)
    
        def validate_password(self, password):
            return check_password_hash(self.password_hash, password)
    

    修改 home/admin.py 中的视图函数,添加登录登出、视图保护的代码:

    from flask import request, Blueprint, render_template, redirect, url_for, flash
    from flask_login import login_user, login_required, current_user, logout_user
    
    from myblog.models import Article, Category, Comment, Admin
    from myblog.forms import LoginForm, AddForm
    from myblog.extensions import db
    
    
    admin_bp = Blueprint('admin', __name__)
    
    
    @admin_bp.route('/login', methods=['POST', 'GET']) 
    def login():
        form = LoginForm()
        if form.validate_on_submit():
            username = form.username.data
            password = form.password.data
            remember = form.remember.data
            admin = Admin.query.first()
    
            if username == admin.username and admin.validate_password(password):
                login_user(admin)
                flash('登录成功', category='info')
                return redirect(url_for('admin.edit'))
            else:
                flash('登录失败', category='warning')
        return render_template('admin/login.html', form=form)
    
    
    @admin_bp.route('/logout')
    @login_required
    def logout():
        logout_user()
        flash('再见!')
        return redirect(url_for('admin.login'))
    
    
    @admin_bp.route('/edit')
    @login_required
    def edit():
        page = request.args.get('page', 1, type=int)
        articles = Article.query.order_by(Article.timestamp.desc()).paginate(page, 10, False)
    
        return render_template('admin/edit.html', articles=articles)
    
    
    @admin_bp.route('/delete/<int:article_id>')
    @login_required
    def delete(article_id):
        article = Article.query.filter(Article.id == article_id).first()
        db.session.delete(article)
        db.session.commit()
        flash('删除成功', category='info')
    
        return redirect(url_for('admin.edit')) 
    
    
    @admin_bp.route('/add', methods=['POST', 'GET'])
    @login_required
    def add():
        form = AddForm()
        if form.validate_on_submit():
            title = form.title.data
            body = form.body.data
            category = form.category.data
    
            article = Article(title=title, body=body, category_id=category)
            db.session.add(article)
            db.session.commit()
            flash('新建博客成功', category='info')
            return redirect(url_for('admin.edit'))
    
        return render_template('admin/add.html', form=form)
    

    在 base.html 中修改导航栏页面,视登录情况显示登录或登出按钮:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        {% block head %}
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> 
            {% block styles %}
                <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}"> {{ bootstrap.load_css() }} 
            {% endblock %} 
            <title>{% block title %}{% endblock %}</title>
        {% endblock %}
    </head>
    
    <body>
        {% for message in get_flashed_messages() %}
            <div class="alert alert-primary" role="alert">
                {{ message }}
            </div>
            {% endfor %}
        {% block nav %}
            <nav class="navbar navbar-expand-lg navbar-light bg-light">
                <div class="container">
                    <a class="navbar-brand" href="#">我的博客</a>
            
                    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                            <span class="navbar-toggler-icon"></span>
                        </button>
            
                    <div class="collapse navbar-collapse" id="navbarSupportedContent">
                        <ul class="navbar-nav mr-auto">
                            <li class="nav-item {% if request.endpoint == 'blog.index' %} active {% endif %}">
                                <a class="nav-link" href="{{ url_for('blog.index') }}">首页<span class="sr-only">(current)</span></a>
                            </li>
                        </ul>
                        
                        <ul class="navbar-nav">
                            {% if current_user.is_authenticated %}
                            <li class="nav-item {% if request.endpoint == 'admin.logout' %} active {% endif %}">
                                <a class="nav-link" href="{{ url_for('admin.logout') }}">登出</a>
                            </li>
                            {% else %}
                            <li class="nav-item {% if request.endpoint == 'admin.login' %} active {% endif %}">
                                <a class="nav-link" href="{{ url_for('admin.login') }}">登录</a>
                            </li>                
                            {% endif %}
                        </ul>
                    </div>
                </div>
            </nav>
        {% endblock nav %}
    
        <div class="container">
            {% block content %}{% endblock%}
        </div>
    
        {% block scripts %}
            {{ bootstrap.load_js() }} 
        {% endblock %}
    
    </body>
    
    </html>
    

    3.相关页面展示

    登录后的后台页面:

    未登录时,后台页面的 edit 视图需要登录才能查看:

  • 相关阅读:
    Hufman编码实现运用1 (原理不描述)
    E
    1178: [Apio2009]CONVENTION会议中心
    1071: [SCOI2007]组队
    #333. 【NOIP2017】宝藏
    CF 96 D. Volleyball
    CF 987 D. Fair
    qbxt的题:运
    qbxt的题:找一个三元环
    4361: isn
  • 原文地址:https://www.cnblogs.com/qxcheng/p/13792648.html
Copyright © 2011-2022 走看看