基于flask的微电影管理系统——后台管理(1)

系统框架

.
|-- app
|   |-- admin
|   |   |-- forms
|   |   |   |-- admin.py
|   |   |   |-- auth.py
|   |   |   |-- __init__.py
|   |   |   |-- main.py
|   |   |   |-- movie.py
|   |   |   |-- preview.py
|   |   |   |-- role.py
|   |   |   `-- tag.py
|   |   |-- __init__.py
|   |   |-- utils.py
|   |   `-- views
|   |       |-- admin.py
|   |       |-- auth.py
|   |       |-- collect.py
|   |       |-- comment.py
|   |       |-- __init__.py
|   |       |-- logs.py
|   |       |-- main.py
|   |       |-- movie.py
|   |       |-- preview.py
|   |       |-- role.py
|   |       |-- tag.py
|   |       `-- user.py
|   |-- home
|   |   |-- forms.py
|   |   |-- __init__.py
|   |   |-- utils.py
|   |   `-- views.py
|   |-- __init__.py
|   |-- models.py
|   |-- static
|   |   |-- asset
|   |   |-- css
|   |   |-- js
|   |   |-- fonts
|   |   |-- img
|   |   `-- upload
|   |       |-- movieImg
|   |       |-- previewImg
|   |       `-- userFaceImg
|   `-- templates
|       |-- admin
|       |   |-- admin
|       |   |   |-- add.html
|       |   |   `-- list.html
|       |   |-- aside.html
|       |   |-- auth
|       |   |   |-- add.html
|       |   |   |-- edit.html
|       |   |   `-- list.html
|       |   |-- base.html
|       |   |-- collect
|       |   |   `-- list.html
|       |   |-- comment
|       |   |   `-- list.html
|       |   |-- login.html
|       |   |-- logs
|       |   |   |-- admin_log.html
|       |   |   |-- operate_log.html
|       |   |   `-- user_log.html
|       |   |-- movie
|       |   |   |-- add.html
|       |   |   |-- edit.html
|       |   |   `-- list.html
|       |   |-- preview
|       |   |   |-- add.html
|       |   |   |-- edit.html
|       |   |   `-- list.html
|       |   |-- pwd.html
|       |   |-- role
|       |   |   |-- add.html
|       |   |   |-- edit.html
|       |   |   `-- list.html
|       |   |-- tag
|       |   |   |-- add.html
|       |   |   |-- edit.html
|       |   |   `-- list.html
|       |   `-- user
|       |       |-- list.html
|       |       `-- view.html
|       |-- home
|       |   |-- base.html
|       |   |-- comments.html
|       |   |-- index.html
|       |   |-- login.html
|       |   |-- moviecollect.html
|       |   |-- play.html
|       |   |-- pwd.html
|       |   |-- register.html
|       |   |-- user.html
|       |   |-- userlog.html
|       |   `-- usermenu.html
|       `-- macro
|           `-- pages.html
|-- config.py
`-- manage.py

后台蓝图的创建

在admin的模块包__init__.py中,创建蓝图连接,导出所有的视图函数

from flask import Blueprint

admin=Blueprint('admin',__name__)

from app.admin.views.main import  *
from app.admin.views.tag import  *
from app.admin.views.movie import  *
from app.admin.views.preview import *
from app.admin.views.user import *
from app.admin.views.comment import *
from app.admin.views.collect import *
from app.admin.views.logs import *
from app.admin.views.auth import *
from app.admin.views.role import *
from app.admin.views.admin import *

在app中的__init__中,添加注册后台的蓝图

from app.admin import admin as admin_blueprint

# 注册admin蓝图, url_prefix='/admin'添加前缀/admin
app.register_blueprint(admin_blueprint, url_prefix='/admin')

主要的:继承的base.html(后台管理的),

{% extends 'bootstrap/base.html' %}

{% block doc %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="">
        <meta name="author" content="Mosaddek">
        <meta name="keyword" content="FlatLab, Dashboard, Bootstrap, Admin, Template, Theme, Responsive, Fluid, Retina">
        <link rel="shortcut icon" href="/static/img/favicon.html">

        <title>微电影-{% block title %}  {% endblock %}</title>

        <!-- Bootstrap core CSS -->
        <link href="/static/css/bootstrap.min.css" rel="stylesheet">
        <link href="/static/css/bootstrap-reset.css" rel="stylesheet">
        <!--external css-->
        <link href="/static/assets/font-awesome/css/font-awesome.css" rel="stylesheet"/>
        <!-- Custom styles for this template -->
        <link href="/static/css/style.css" rel="stylesheet">
        <link href="/static/css/style-responsive.css" rel="stylesheet"/>

        <!-- HTML5 shim and Respond.js IE8 support of HTML5 tooltipss and media queries -->
        <!--[if lt IE 9]>
      <script src="/static/js/html5shiv.js"></script>
      <script src="/static/js/respond.min.js"></script>
    <![endif]-->
    </head>

    <body>

    <section id="container">
        <!--header start-->
        <header class="header white-bg">
            <div class="sidebar-toggle-box">
                <div data-original-title="Toggle Navigation" data-placement="right" class="icon-reorder tooltips"></div>
            </div>
            <!--logo start-->
            <a href="#" class="logo">微电影<span>后台管理系统</span></a>
            <!--logo end-->

            <div class="top-nav ">
                <ul class="nav pull-right top-menu">
                    <li>
                        <input type="text" class="form-control search" placeholder="Search">
                    </li>
                    <!-- user login dropdown start-->
                    <li class="dropdown">
                        <a data-toggle="dropdown" class="dropdown-toggle" href="#">
                            <img alt="" src="/static/img/avatar1_small.jpg">
                            <span class="username">西部开源技术中心</span>
                            <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu extended logout">
                            <div class="log-arrow-up"></div>
                            <li><a href="#"><i class=" icon-suitcase"></i>配置</a></li>
                            <li><a href="{{ url_for('admin.pwd') }}"><i class="icon-cog"></i> 修改密码</a></li>
                            <li><a href="#"><i class="icon-bell-alt"></i> 会员中心</a></li>
                            <li><a href="{{ url_for('admin.logout') }}"><i class="icon-key"></i> 登出</a></li>
                        </ul>
                    </li>
                    <!-- user login dropdown end -->
                </ul>
            </div>
        </header>
        <!--header end-->
        {% include 'admin/aside.html' %}


        <!--main content start-->
        <section id="main-content">

            <section class="wrapper" style="margin-left: 20px;">
                {#让每个页面都可以获取闪现信息闪现#}
                {% for item in get_flashed_messages() %}

                    <div class="alert alert-warning alert-dismissible" role="alert">
                        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
                                aria-hidden="true">&times;</span></button>
                        {{ item }}
                    </div>
                {% endfor %}

                {#   参考 路径导航:  https://v3.bootcss.com/components/#breadcrumbs           #}
                <h1>微电影管理系统</h1>
                <ol class="breadcrumb">
                    <li><a href="#"><i class="fa fa-dashboard"></i> 首页</a></li>
                    <li class="active">控制面板</li>
                </ol>


                {% block content %}
                    <!-- page start-->
                    Page content goes here
                    <!-- page end-->
                {% endblock %}
            </section>
        </section>
        <!--main content end-->
    </section>

    <!-- js placed at the end of the document so the pages load faster -->
    <script src="/static/js/jquery.js"></script>
    <script src="/static/js/bootstrap.min.js"></script>
    <script src="/static/js/jquery.scrollTo.min.js"></script>
    <script src="/static/js/jquery.nicescroll.js" type="text/javascript"></script>


    <!--common script for all pages-->
    <script src="/static/js/common-scripts.js"></script>


    </body>
    </html>

{% endblock %}

册边栏的页面实现:aside.html

<!--sidebar start-->
<aside style="margin-right: 100px">
    <div id="sidebar" class="nav-collapse ">
        <!-- sidebar menu start-->
        <ul class="sidebar-menu">
            <li class="">
                <a class="" href="{{ url_for('admin.index') }}">
                    <i class="icon-dashboard"></i>
                    <span>电脑信息</span>
                </a>
            </li>
            <li class="sub-menu">
                <a href="javascript:;" class="">
                    <i class="icon-book"></i>
                    <span>标签管理</span>
                    <span class="label label-danger pull-right">2</span>

                    <span class="arrow"></span>
                </a>
                <ul class="sub">
                    <li><a class="" href="{{ url_for('admin.tag_add') }}">增加标签</a></li>
                    <li><a class="" href="{{ url_for('admin.tag_list') }}">标签列表</a></li>

                </ul>
            </li>
            <li class="sub-menu">
                <a href="javascript:;" class="">
                    <i class="icon-cogs"></i>
                    <span>电影管理</span>
                    <span class="label label-danger pull-right">2</span>
                    <span class="arrow"></span>
                </a>
                <ul class="sub">
                    <li><a class="" href="{{ url_for('admin.movie_add') }}">增加电影</a></li>
                    <li><a class="" href="{{ url_for('admin.movie_list') }}">电影列表</a></li>

                </ul>
            </li>
            <li class="sub-menu">
                <a href="javascript:;" class="">
                    <i class="icon-tasks"></i>
                    <span>预告管理</span>
                    <span class="label label-danger pull-right">2</span>
                    <span class="arrow"></span>
                </a>
                <ul class="sub">
                    <li><a class="" href="{{ url_for('admin.preview_add') }}">添加预告</a></li>
                    <li><a class="" href="{{ url_for('admin.preview_list') }}">预告列表</a></li>

                </ul>
            </li>
            <li class="">
                <a class="" href="{{ url_for('admin.user_list') }}">
                    <i class="icon-dashboard"></i>
                    <span>会员管理</span>
                </a>
            </li>
            <li class="">
                <a class="" href="{{ url_for('admin.comment_list') }}">
                    <i class="icon-dashboard"></i>
                    <span>评论管理</span>
                </a>
            </li>
            <li class="">
                <a class="" href="{{ url_for('admin.collect_list') }}">
                    <i class="icon-dashboard"></i>
                    <span>收藏管理</span>
                </a>
            </li>

            <li class="sub-menu">
                <a href="javascript:;" class="">
                    <i class="icon-th"></i>
                    <span>日志管理</span>
                    <span class="label label-danger pull-right">3</span>
                    <span class="arrow"></span>
                </a>
                <ul class="sub">
                    <li><a class="" href="{{ url_for('admin.logs_operate_log') }}">管理员操作日志</a></li>
                    <li><a class="" href="{{ url_for('admin.logs_admin_log') }}">管理员登录日志</a></li>
                    <li><a class="" href="{{ url_for('admin.logs_user_log') }}">会员登录日志</a></li>
                </ul>
            </li>

            <li class="sub-menu">
                <a href="javascript:;" class="">
                    <i class="icon-envelope"></i>
                    <span>权限管理</span>
                    <span class="label label-danger pull-right">2</span>
                    <span class="arrow"></span>
                </a>
                <ul class="sub">
                    <li><a class="" href="{{ url_for('admin.auth_add') }}">添加权限</a></li>
                    <li><a class="" href="{{ url_for('admin.auth_list') }}">权限列表</a></li>

                </ul>
            </li>


            <li class="sub-menu">
                <a href="javascript:;" class="">
                    <i class="icon-glass"></i>
                    <span>角色管理</span>
                    <span class="label label-danger pull-right">2</span>
                    <span class="arrow"></span>
                </a>
                <ul class="sub">
                    <li><a class="" href="{{ url_for('admin.role_add') }}">添加角色</a></li>
                    <li><a class="" href="{{ url_for('admin.role_list') }}">角色列表</a></li>
                </ul>
            </li>
            <li class="sub-menu">
                <a href="javascript:;" class="">
                    <i class="icon-user"></i>
                    <span>管理员管理</span>
                    <span class="label label-danger pull-right">2</span>
                    <span class="arrow"></span>
                </a>
                <ul class="sub">
                    <li><a class="" href="{{ url_for('admin.admin_add') }}">添加管理员</a></li>
                    <li><a class="" href="{{ url_for('admin.admin_list') }}">管理员列表</a></li>
                </ul>
            </li>
        </ul>
        <!-- sidebar menu end-->
    </div>
</aside>
<!--sidebar end-->

实现各个页面的分页显示,运用html中函数的方法:宏,即macro包中的pages.html

{% macro paginate(PageObj, viewFun) %}
    <div class="col-md-12 text-center">
        <nav aria-label="Page navigation">
            <ul class="pagination">
                <li>
                    <a href="{{ url_for(viewFun, page=1) }}" aria-label="First">
                        <span aria-hidden="true">首页</span>
                    </a>
                </li>
                {% if PageObj.has_prev %}
                    <li>
                        <a href="{{ url_for(viewFun, page=PageObj.prev_num) }}" aria-label="Previous">
                            <span aria-hidden="true">上一页</span>
                        </a>
                    </li>
                {% else %}
                    <li class="disabled">
                        <a aria-label="Previous">
                            <span aria-hidden="true">上一页</span>
                        </a>
                    </li>
                {% endif %}
                <li><a href="#">{{ PageObj.page }}&nbsp;/&nbsp;{{ PageObj.pages }}</a></li>
                {% if PageObj.has_next %}
                    <li>
                        <a href="{{ url_for(viewFun, page=PageObj.next_num) }}" aria-label="Next">
                            <span aria-hidden="true">下一页</span>
                        </a>
                    </li>
                {% else %}
                    <li class="disabled">
                        <a aria-label="Next">
                            <span aria-hidden="true">下一页</span>
                        </a>
                    </li>

                {% endif %}
                <li>
                    <a href="{{ url_for(viewFun, page=PageObj.pages) }}" aria-label="Last">
                        <span aria-hidden="true">尾页</span>
                    </a>
                </li>
            </ul>
        </nav>
    </div>


{% endmacro %}

admin包里实现各种函数以及装饰器的模块:utils.py中

from functools import wraps

from flask import session, flash, redirect, url_for, request, abort

from app import db
from app.models import AdminOplog, Admin, Auth


def is_admin_login(f):
    """用来判断用户是否登录成功"""

    @wraps(f)
    def wrapper(*args, **kwargs):
        # 判断session对象中是否有seesion['admin'],
        # 如果包含信息, 则登录成功, 可以访问主页;
        # 如果不包含信息, 则未登录成功, 跳转到登录界面;;
        if session.get('admin', None):
            return f(*args, **kwargs)
        else:
            flash("管理员必须登录才能访问%s" % (f.__name__))
            return redirect(url_for('admin.login'))

    return wrapper

def write_adminlog(content):
    """将操作日志写入数据库中"""
    adminOplog = AdminOplog(
        admin_id=session.get('admin_id'),
        content=content,
        ip=request.remote_addr
    )
    db.session.add(adminOplog)
    db.session.commit()

def permission_control(f):
    """判断管理员是否有权限操作,(如果是超级管理员, 则全部可以操作) 如果没有权限抛出403"""
    @wraps(f)
    def wrapper(*args, **kwargs):
        admin = Admin.query.get_or_404(session.get('admin_id'))
        if not admin.is_super:  # 如果不是超级用户, xxxx
            # 获取当前用户拥有的权限, 默认是字符串'1,2,3'
            auths = admin.role.auths
            # 获取所有的权限列表;
            all_auth = Auth.query.all()
            # 获取管理员可以访问的路由地址
            admin_urls = []
            auths = map(int, auths.split(','))  # 权限id号
            for auth in all_auth:
                for auth_id in auths:
                    # 若管理员有全部权限中的某一项,则添加到该管理员的可访问路由地址中
                    if auth_id == auth.id:
                        admin_urls.append(auth.url)
            print("管理员可以访问的路由地址:", admin_urls)
            print("管理员正在访问的url路由地址:", request.url_rule)

            if str(request.url_rule) not in admin_urls:
                abort(404)
        return f(*args, **kwargs)

    return wrapper

forms模块包中分别创建各页面的表单,便于管理;views包以及templates中admin的页面实现的html文件也分区域便于管理

一.(1)主页面的实现。主页,登录页面以及登出,和更改密码的表单

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, FileField, TextAreaField
from wtforms.validators import DataRequired, Length, EqualTo, Email, Regexp
from flask_wtf.file import FileAllowed


class BaseForm(FlaskForm):
    username = StringField(
        label="用户名",
        validators=[
            DataRequired()

        ]
    )
    password = PasswordField(
        label="密码",
        validators=[
            DataRequired(),
            # Length(6, 12, message="密码长度必须为6-12")

        ]
    )


class LoginForm(BaseForm):
    submit = SubmitField(
        label="登录"
    )




class PwdForm(FlaskForm):
    old_pwd = PasswordField(
        label="旧密码",
        validators=[
            DataRequired()
        ],
    # <input name="xxx" placeholder="">
    render_kw = {
        'placeholder' : "请输入旧密码"
    }
    )
    new_pwd = PasswordField(
        label="新密码",
        validators=[
            DataRequired()
        ],
        render_kw={
            'placeholder': "请输入新密码"
        }
    )

    submit = SubmitField(
        label="修改密码"
    )

(2)对应的视图函数

from flask import session, flash, request, redirect, url_for, render_template
from werkzeug.security import generate_password_hash

from app import db
from app.admin import admin
from app.admin.forms.main import LoginForm, PwdForm
from app.admin.utils import is_admin_login
from app.models import  Admin, Adminlog

@admin.route('/')
def index():
    return  render_template('admin/base.html')


@admin.route('/login/', methods=['POST', 'GET'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        name = form.username.data
        password = form.password.data
        admin = Admin.query.filter_by(name=name).first()
        if admin and admin.verify_password(password):
            # session信息的保存
            session['admin_id'] = admin.id
            session['admin'] = admin.name
            flash("管理员%s登录成功" % (admin.name))
            remote_ip = request.remote_addr
            # 将登录信息写到日志中;
            adminlog = Adminlog(admin_id=admin.id,
                              ip=remote_ip,
                              area='xxx内网IP')
            db.session.add(adminlog)
            db.session.commit()

            # 从index蓝图里面寻找index函数;
            return redirect(url_for('admin.index'))
        else:
            flash("管理员登录失败")
            return redirect(url_for('admin.login'))
    return render_template('admin/login.html',
                           form=form)


@admin.route('/logout/')
@is_admin_login
def logout():
    session.pop('admin_id', None)
    session.pop('admin', None)
    return redirect(url_for('admin.login'))



# 修改密码
@admin.route('/pwd/', methods=['GET', 'POST'])
def pwd():
    form = PwdForm()
    if form.validate_on_submit():
        # 获取当前登录用户的密码
        admin = Admin.query.filter_by(name=session.get('admin')).first()
        # 判断用户的旧密码是否正确
        if admin.verify_password(form.old_pwd.data):
            # ********数据库里面的是password
            admin.password = generate_password_hash(form.new_pwd.data)
            db.session.add(admin)
            db.session.commit()
            flash("密码更新成功")
        else:
            flash("旧密码错误, 请重新输入")
        return redirect(url_for('admin.pwd'))
    return render_template('admin/pwd.html', form=form)

(3)对应的templates中改组的html文件

主页即为base页面

在这里插入图片描述

登录页面的实现:login.html

登录前必须创建一个超级用户,页面是不能创建用户的
在数据库的操作的时候,已经添加该命令,查看基于flask的微电影的数据库创建那节

{% extends 'bootstrap/base.html' %}
{% import 'bootstrap/wtf.html'  as wtf %}


{% block title %}
    登录
{% endblock %}


{% block content %}
    <div class="container">
        <div class="col-lg-8 col-lg-offset-2">


            <div class="panel panel-success">
                <div class="panel-heading">
                    <h1 class="panel-title"><span class="glyphicon glyphicon-log-in">

                    </span>&nbsp;&nbsp;登录</h1>
                </div>
                <div class="panel-body">
                    {{ wtf.quick_form(form) }}
                </div>
            </div>

        </div>


    </div>

{% endblock %}

在这里插入图片描述

更改密码的页面实现:pwd.html
{% extends 'admin/base.html' %}
{% import 'bootstrap/wtf.html'  as wtf %}

{% block title %}

    修改密码
{% endblock %}


{% block content %}



        {#  右侧用户中心       #}
        <div class="col-lg-11">
            {#   面板中心          #}
            <div class="panel panel-warning">
                {#   面板头部              #}
                <div class="panel-heading">
                    <h3 class="panel-title">
                        <span class="glyphicon glyphicon-lock"></span>&nbsp;修改密码
                    </h3>
                </div>
                {#   面板主体               #}
                <div class="panel-body">
                    {{ wtf.quick_form(form) }}
                </div>
            </div>

        </div>


{% endblock %}


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/GLH_2236504154/article/details/88901416