【python】day10-14 flask框架——电影网站(持续更新中)

目录

1.新建项目

2.进行项目

1.新建readme.txt文件对整个项目进行文字说明

2.按照文字说明进行步骤

1.导入数据库

2.新建app包

3.新建manage.py文件

4.app包下 init.py文件添加代码

5.app包下 新建 admin包

6.templates文件夹下 新建admin包

7.设置修改运行的文件

8.templates/admin/login.html 修改页面

9.admin/views文件中

10.app中新建models.py文件

11.补全views.py文件中login函数

12.views.py中新建index函数

13.admin中新建index.html

14.运行起来  登录

15.修改index.html页面

16. 新建admin.html并编写

17. 新建grid.html菜单页面

18. 修改views.py文件中 添加管理员日志

19. 标签管理-添加标签

20.标签管理-标签列表

21.标签管理-标签编辑

22.标签管理-标签删除

23.电影管理-添加电影

24.电影管理-电影列表

25.电影管理-电影编辑

26.电影管理-电影删除

27.预告管理-添加预告

28.预告管理-预告列表

29.预告管理-预告编辑

30.预告管理-预告删除

31.会员管理-会员列表

32.会员管理-会员删除

33.会员管理-会员查看

34.评论管理-评论列表

35.评论管理-评论删除

36.收藏管理-收藏列表

37.收藏管理-收藏删除

38.日志管理

39.权限管理

40.角色管理

41.管理员管理


1.新建项目

进入后界面

运行点击网址

 显示结果

这样就没问题了 

2.进行项目

1.新建readme.txt文件对整个项目进行文字说明

2.按照文字说明进行步骤

1.导入数据库

    1.1 movie.sql文件导入到mysql数据库中

2.新建app包

   static,templates放到app包中存放

   2.1 static===>存放公共的资源 js/css/jquery/image

   2.2 templates===>存储界面文件 html/jsp

   2.3 将app.py删除

3.新建manage.py文件

    3.1 JSNUMovie文件夹下创建manage.py

     见上图

    3.2 manage.py文件代替app.py的功能

'''
Manage项目运行的主入口
'''
# 导入上方的app包里面的内容
from app import app
from flask_script import Manager

# 1.设置业务管理文件
manage=Manager(app)

# 2.运行Flask管理模块
if __name__=='__main__':
    manage.run()

    3.3 flask_script报错

        cmd===>pip install flask-script 下载第三方模块

4.app包下 init.py文件添加代码

    下载第三方模块

    cmd===>pip install flask-sqlalchemy  (数据库的驱动功能包)

    cmd===>pip install flask-redis (缓存机制功能包)

    4.1 设置项目名称

    4.2 设置数据连接

    4.3 设置项目缓存

    4.4 设置DEBUG模式

    4.5 数据库连接

    4.6 设置缓存机制

    4.7 设置蓝图(提高编程效率)

'''
app/__init__.py
    1 设置项目名称
    2 设置数据连接
    3 设置项目缓存
    4 设置DEBUG模式
    5 数据库连接
    6 设置缓存机制
    7 设置蓝图(提高编程效率)

    cmd===>pip install flask-sqlalchemy  (数据库的驱动功能包)
    cmd===>pip install flask-redis (缓存机制功能包)
'''
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_redis import FlaskRedis

# 设置作者
__author__='zq'

'''1.设置名称'''
app=Flask(__name__)

'''2.设置数据库连接'''
# 2.1 设置mysql连接参数
# mysql+mysqlconnector===>msyql数据库+mysql的驱动模块
# root:mysql====>用户名和密码
# 127.0.0.1:3306===>ip地址+3306端口号  localhost公认的本机地址
# movie==>数据库名称
app.config['SQLALCHEMY_DATABASE_URI']=\
    'mysql+mysqlconnector://root:123456@127.0.0.1:3306/movie'

# 2.2 设置mysql对象修改与信号发送
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True

'''3.设置项目缓存'''
# 3.1 设置缓存的URL
app.config['REDIS_URL']='redis://127.0.0.1:6379/0'
# 3.2 设置秘钥
app.config['SECRET_KEY']='zpp_movie'
# 3.3 设置上传的目录
# os.path.join ===>目录拼接函数
# os.path.abspath===>绝对路径 E:\PycharmProjects\JSNUMovie
# os.path.dirname(__file__)===>E:\PycharmProjects\JSNUMovie\app\static\uploads\
# __file__ ===>app包
# 后端上传的目录
app.config['UP_DIR']=\
    os.path.join(
        os.path.abspath(os.path.dirname(__file__)),'static/uploads/')

#前端上传目录
app.config['FC_DIR']=\
    os.path.join(
        os.path.abspath(os.path.dirname(__file__)),"static/uploads/users"
    )

# 4.设置DEBUG模式
app.debug=False

# 5.数据库连接
db=SQLAlchemy(app)

# 6.设置缓存机制
rd=FlaskRedis(app)

'''7.设置蓝图'''
# 调用app包下admin包 导入admin功能  别名 admin_blueprint
# 7.1 设置导入蓝图
from app.admin import admin as admin_blueprint

# 7.2 注册蓝图
# 127.0.0.1:5000/admin/
app.register_blueprint(admin_blueprint,url_prefix='/admin')

5.app包下 新建 admin包

    5.1 admin包下__init__.py设置当前模块蓝图的名称

    5.2 admin包下 新建views文件

    5.3 admin/views login函数

admin下的__init__.py

'''
app/admin/__init__.py
'''
from flask import Blueprint
# 设置当前模块的蓝图 名称 admin
admin=Blueprint('admin',__name__)

import app.admin.views

admin下的views.py

'''
app/admin/views
管理员模块  视图文件
后台登录系统
'''
# 1.登录功能实现
from flask import render_template
from . import admin

@admin.route("/login/",methods=['GET','POST'])
def login():
    # 1.测试语句
    print("登录模块")
    return render_template("admin/login.html")

6.templates文件夹下 新建admin包

    6.1 admin包下 新建login.html

 运行login.html

7.设置修改运行的文件

    7.1 打开右上角Add Configuration....

        选择Edit Configurations

        选择左上角的+

        选择python

        修改Name===>MovieManager

        添加Parameters===>runserver

        添加Script path===>选择JSNUMovie文件夹下manage.py文件

    7.2 点击右上角的播放按钮

    7.3 打开控制台 127.0.0.1:5000 打开浏览器

    7.4 输入URL 127.0.0.1:5000/admin/login

        查看是否进入login.html

8.templates/admin/login.html 修改页面

    8.1 网站素材 复制粘贴到  static文件夹下

    8.2 修改login.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台页面</title>
    <!--解决IE浏览器兼容问题-->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <!--width-device-width:页面的可视区域-->
    <!--initial-scale=?:显示可视区域缩放级别1.0-->
    <!--maximum-scale=?最大缩放值-->
    <!--minimum-scale=?最小缩放值-->
    <!--use-scalable=yes/no:表示用户可以手动缩放-->
    <!--name='viewport':手机端页面虚拟窗口-->
    <meta content="width=device-width,initial-scale-1,user-scalable=no" name="viewport">
    <link rel="shortct icon" href="{{ url_for('static',filename='base/images/login.png') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='fonts/css/font-awesome.min.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='ionicons/css/ionicons.min.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/dist/css/AdminLTE.min.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/plugins/iCheck/square/blue.css') }}">
</head>
<body class="hold-transition login-page" style="text-align: center">
    <div class="login-box">
        <div class="login-logo">
            <b>星空电影管理系统</b>
        </div>
        <div class="login-box-body">
            <!--设置登录信息显示-->
            <!--失败-->
            {% for msg in get_flashed_messages(category_filter=['err']) %}
                <p class="login-box-msg" style="color: red">{{ msg }}</p>
            {% endfor %}
            <!--成功-->
            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                <p class="login-box-msg" style="color: green">{{ msg }}</p>
            {% endfor %}
            <!--设置表单提交-->
            <form method="post" id="form-data">
                <!--账号-->
                <div class="form-group has-feedback" style="height: 30px">
                    {{ form.account }}
                    <span class="glyphicon glyphicon-envelope form-control-feedback">
                    </span>

                    {% for err in form.account.errors %}
                        <div class="col-md-12">
                            <p style="color: red">{{ err }}</p>
                        </div>
                    {% endfor %}
                </div>
                <!--密码-->
                <div class="form-group has-feedback" style="height: 30px">
                    {{ form.pwd }}
                    <span class="glyphicon glyphicon-envelope form-control-feedback">

                    </span>
                    {% for err in form.pwd.errors %}
                        <div class="col-md-12">
                            <p style="color: red">{{ err }}</p>
                        </div>
                    {% endfor %}
                </div>
                <!--登录按钮-->
                <div class="row">
                    <div class="col-xs-8"></div>
                    <div class="col-xs-4">
                        <!--令牌,保护验证的-->
                        {{ form.csrf_token }}
                        {{ form.submit }}
                    </div>
                </div>
            </form>
        </div>
    </div>
<!--加载js文件-->
<script src="{{ url_for('static',filename='admin/plugins/jQuery/jQuery-2.2.0.min.js') }}"></script>
<script src="{{ url_for('static',filename='admin/bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static',filename='admin/plugins/iCheck/icheck.min.js') }}"></script>

</body>
</html>

9.admin/views文件中

    9.1 修改login函数

    9.2 新建forms文件

        cmd===>pip install flask-wtf

    9.3 编写LoginForm类

'''
后台登录 表单
flask_wtf是flask框架的表单验证模块,可以很方便生成表单,也可以当做json数据交互的验证工具

flask框架中内部并没有提供全面的表单验证,所以当我们不借助第三方插件来处理代码会显得混乱
官方推荐的一个表单验证插件就是wtforms
wtform是一个支持多种web框架的form组件,主要用于对用户请求数据进行验证
wtforms按照功能类别分类由以下几个类别:
Forms:主要用于表单验证、字段定义、HTML生成,并把各种验证流程聚集在一起进行验证
Fields:主要负责渲染(生成HTML)和数据转换 zq===>account='zq'
Validator:主要用于验证用户输入的数据合法性,比如Length验证器用户验证输入数据的长度
Widgets:html插件,允许使用者在字段中通过该字典自定义html小部件
Meta:用于使用者定义wtfomrs功能,例如csrf的功能开启
Extensions:丰富的扩展库,可以与其他框架结合使用,例如django
'''
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,SubmitField
from wtforms.validators import DataRequired,ValidationError

from app.models import Admin

# 1.管理员登录表单
class LoginForm(FlaskForm):
    # validators:验证器
    # description:描述
    # render_kw:渲染属性
    account = StringField(
        label="账号",
        validators=[DataRequired("账号不能为空")],
        description="管理员账号",
        render_kw={
            'class':'form-control',
            'placeholder':'请输入账号'
        }
    )
    pwd = PasswordField(
        label="密码",
        validators=[DataRequired("密码不能为空")],
        description="管理员密码",
        render_kw={
            'class':'form-control',
            'placeholder':'请输入密码'
        }
    )
    submit=SubmitField(
        label='登录',
        render_kw={
            'class':'btn btn-primary btn-block btn-flat'
        }
    )
    # 根据账号查询数据是否存在 field ===>account的值
    def validat_account(self,field):
        # 获取账号的值
        account = field.data
        # 查询操作models
        admin = Admin.query.filter_by(name=account).count()
        if admin==0:
            raise ValidationError("账号不存在!")

10.app中新建models.py文件

'''
模型层
跟数据库中表一一对应
'''
# 调用init文件中的db属性
from app import db
from datetime import datetime
# 1.管理员
class Admin(db.Model):
    # 1.设置表格名称(数据库表一致)
    __tablename__='admin'
    # 2.表格是否存在
    __table_args__={'useexisting':True}
    # 3.设置映射
    id = db.Column(db.Integer,primary_key=True)# 编号
    name=db.Column(db.String(100),unique=True)# 管理员账号
    pwd = db.Column(db.String(100))# 管理员密码
    is_super=db.Column(db.SmallInteger)# 是否为超级管理员 0为超级管理员
    role_id=db.Column(db.Integer)# 所属角色
    addtime=db.Column(db.DateTime,index=True,default=datetime.now)
    # '''外键关联'''
    # adminlogs=db.relationship('Adminlog',backref='admin')# 管理员登录日志外键关联
    # oplogs=db.relationship("Oplog",backref='admin')
    # 4.显示对象属性
    def __repr__(self):
        return '<Admin %r>'%self.name
    # 5.检查密码
    def check_pwd(self,pwd):
        # 系统密码
        print("系统密码:",self.pwd)
        # 用户密码
        print("用户密码:",pwd)
        return self.pwd == pwd

    10.1 编写Admin类

'''
模型层
跟数据库中表一一对应
'''
# 调用init文件中的db属性
from app import db
from datetime import datetime
# 1.管理员
class Admin(db.Model):
    # 1.设置表格名称(数据库表一致)
    __tablename__='admin'
    # 2.表格是否存在
    __table_args__={'useexisting':True}
    # 3.设置映射
    id = db.Column(db.Integer,primary_key=True)# 编号
    name=db.Column(db.String(100),unique=True)# 管理员账号
    pwd = db.Column(db.String(100))# 管理员密码
    is_super=db.Column(db.SmallInteger)# 是否为超级管理员 0为超级管理员
    rold_id=db.Column(db.Integer)# 所属角色
    # '''外键关联'''
    # adminlogs=db.relationship('Adminlog',backref='admin')# 管理员登录日志外键关联
    # oplogs=db.relationship("Oplog",backref='admin')
    # 4.显示对象属性
    def __repr__(self):
        return '<Admin %r>'%self.name
    # 5.检查密码
    def check_pwd(self,pwd):
        # 系统密码
        print("系统密码:",self.pwd)
        # 用户密码
        print("用户密码:",pwd)
        return self.pwd == pwd

11.补全views.py文件中login函数

 

 

'''
app/admin/views
管理员模块  视图文件
后台登录系统
'''
# 1.登录功能实现
from flask import render_template
from . import admin
from app.admin.forms import LoginForm

@admin.route("/login/",methods=['GET','POST'])
def login():
    #1.获取登录表单
    form=LoginForm()
    return render_template("admin/login.html",form=form)

运行

12.views.py中新建index函数

'''
app/admin/views
管理员模块  视图文件
后台登录系统
'''
# 1.登录功能实现
from flask import render_template,flash,redirect,url_for,session
from . import admin
from app.admin.forms import LoginForm
from app.models import Admin

#1.登录功能实现
@admin.route("/login/",methods=['GET','POST'])
def login():
    #1.获取登录表单
    form=LoginForm()
    # 2.判断是否提交按钮
    if form.validate_on_submit():
        # 3.获取表单数据
        data=form.data
        # 4.判断账号是否一致
        # query查询
        # name缺省值参数
        # data数据{'account':'admin','pwd':'123'}
        # first() 第一个被查询出来的值 将查询出来的数据保存成Admin的实体类
        admin=Admin.query.filter_by(name=data['account']).first()
        # 5.判断密码是否一致
        if admin==None or not admin.check_pwd(data['pwd']):
            # 5.1通过flash发送错误信息
            flash("用户名或密码错误",'err')
            # 5.2 重定向请求
            return redirect(url_for('admin.login'))
        # 6.如果都正确 则保存session
        session['admin']=data['account']
        session['admin_id']=admin.id
        # 7.设置管理员日志
        # 8.数据库添加session add是数据库添加操作
        # 9.输出结果
        print("登录成功")
        # 10.重定向
        # 当需要获取前端页面表单传过来的id值的时候,我们需要使用request.args.get
        # request.args.get('next') 获取请求的单个参数
        return redirect(url_for('admin.index'))

    return render_template("admin/login.html",form=form)
# 2.系统首页
@admin.route("/")
def index():
    return render_template("admin/index.html")

13.admin中新建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台首页</title>
</head>
<body>
    <p>主界面</p>
</body>
</html>

14.运行起来  登录

    缺少mysql模块

    cmd===>pip install mysql-connector

15.修改index.html页面

    15.1 头部区域  admin.html

    15.2 主区域  显示主页的内容的

    15.3 底部区域 js区域

<!--1.头部页面  继承-->
{% extends 'admin/admin.html' %}

<!--2.主区域-->
{% block content %}
    <!--第一区段:路径显示-->
    <section class="content-header">
        <h1>星空电影管理系统</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i>
                    首页
                </a>
            </li>
            <li class="active">
                控制面板
            </li>
        </ol>
    </section>
    <!--第二区段-->
    <section class="content" id="showcontent">
        <!--内存使用率-->
        <div class="row">
            <div class="col-md-6">
                <div class="box box-primary">
                    <div class="box-header with-border">
                        <h3>内存使用率</h3>
                    </div>
                    <div class="box-body" id="meminfo"
                         style="height: 600px">
                    </div>
                </div>
            </div>
            <!--系统设置-->
            <div class="col-md-6">
            <div class="box box-primary">
                <div class="box-header with-border">
                    <h3 class="box-title">系统设置</h3>
                </div>
                <!--限制速率大小  限制内存  限制客户端数量-->
                <form role="form">
                    <div class="box-body" style="height: 600px">
                        <!--1.限制速率大小-->
                        <div class="form-group">
                            <label for="input_speed">限制速率大小</label>
                            <input type="text" class="form-control"
                                   id="input_speed"
                                   placeholder="请输入限制速率" value="512">
                        </div>
                        <!--2.限制内存大小-->
                        <div class="form-group">
                            <label for="input_mem">限制内存大小</label>
                            <input type="text" class="form-control"
                                   id="input_mem"
                                   placeholder="请输入限制内存" value="10M">
                        </div>
                        <!--3.限制客户端数量-->
                        <div class="form-group">
                            <label for="input_num">限制客户端数量</label>
                            <input type="text" class="form-control"
                                   id="input_num"
                                   placeholder="请输入限制客户端数量" value="4">
                        </div>
                        <!--4.保存按钮-->
                        <div class="form-group">
                            <button type="submit" class="btn btn-primary">保存并重启服务</button>
                        </div>
                    </div>
                </form>
            </div>
            </div>
        </div>
    </section>
{% endblock %}
<!--3. js区域-->
{% block js %}
    <!--3.1 加载js文件-->
    <script src="{{ url_for('static',filename='js/echarts.min.js')}}"></script>
    <!--3.2 调用显示的标签-->
    <script>
        var myChart = echarts.init(document.getElementById('meminfo'))
        option = {
            backgroundcolor:'white',
            tooltip:{
                formatter:"{a} <br/>{b} : {c}%"
            },
            toolbox:{
                feature:{
                    restore:{},
                    saveAsImage:{}
                }
            },
            series:[{
                name:'内存使用率',
                type:'gauge',
                detail:{
                    formatter:'{value}%'
                },
                data:[{
                    value:50,
                    name:'内存使用率'
                }]
            }]
        };
        // 设置时间 2000毫秒执行一次内部代码
        setInterval(function (){
            // 默认是50的值
            option.series[0].data[0].value = (Math.random() * 100).toFixed(2) - 0;
            myChart.setOption(option,true)
        },2000);
    </script>
    <!--3.3 将左侧菜单<控制面板>样式调整-->
    <script>
        $(document).ready(function (){
            $("#g-1").addClass("active");
            $("#g-1-1").addClass("active");
        });
    </script>

{% endblock %}

16. 新建admin.html并编写

16.1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台浏览器</title>
    <!--解决IE浏览器问题-->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta content="width=device-width,initial-scale-1,user-scalable=no"
          name="viewport">
        <link rel="shortcut icon" href="{{ url_for('static',filename='base/images/logo.png') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='fonts/css/font-awesome.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/bootstrap/css/bootstrap.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='ionicons/css/ionicons.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/dist/css/AdminLTE.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/dist/css/skins/_all-skins.css') }}">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='admin/plugins/datepicker/datepicker3.css') }}">
    <!--设置界面的总样式-->
    <style>
        *{
            font-family: 'Microsoft YaHei',sans-serif;
        }
        .table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{
            vertical-align: middle;
            text-align: center;
        }
    </style>
    {% block css %}
        <!--其他页面CSS样式编写区域-->
    {% endblock %}
</head>
<body class="hold-transition skin-blue sidebar-mini">
    <div class="wrapper">
        <!--1.头部标签区域-->
        <header class="main-header">
            <!--1.1 左侧系统名称-->
            <a href="{{ url_for('admin.index') }}" class="logo">
                <span>
                    <img src="{{ url_for('static',filename='base/images/logo.png') }}"
                         style="height: 40px;width: 40px"/>
                    星空电影系统
                </span>
                <span class="logo-lg">
                    <img src="{{ url_for('static',filename='base/images/logo.png') }}"
                        style="height: 40px;width: 40px"/>
                    电影管理系统
                </span>
            </a>
            <!--1.2 右侧下拉菜单(用户名显示  修改密码  退出系统)-->
            <nav class="navbar navbar-static-top">
                <a href="#" class="sidebar-toggle" data-toggle="offcanvas" rel="button">
                    <span class="sr-only">下拉菜单</span>
                </a>
                <div class="navbar-custom-menu">
                    <ul class="nav navbar-nav">
                         <!--1.2.1 用户名显示以及图像-->
                        <li class="dropdown user user-menu">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                                <img src="{{ url_for('static',filename='admin/dist/img/mtianyan.jpg') }}"
                                    class="user-image" alt="User Image"/>
                                <span class="hidden-xs">{{ session['admin'] }}</span>
                            </a>
                        </li>
                    </ul>
                </div>
            </nav>
        </header>
    </div>
</body>
</html>

 16.2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台浏览器</title>
    <!--解决IE浏览器问题-->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta content="width=device-width,initial-scale-1,user-scalable=no"
          name="viewport">
    <link rel="shortcut icon" href="{{ url_for('static',filename='base/images/logo.png') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='fonts/css/font-awesome.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/bootstrap/css/bootstrap.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='ionicons/css/ionicons.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/dist/css/AdminLTE.css') }}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/dist/css/skins/_all-skins.css') }}">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='admin/plugins/datepicker/datepicker3.css') }}">
    <!--设置界面的总样式-->
    <style>
        *{
            font-family: 'Microsoft YaHei',sans-serif;
        }
        .table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{
            vertical-align: middle;
            text-align: center;
        }
    </style>
        *{
            font-family: 'Microsoft YaHei',sans-serif;
        }
        .table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{
            vertical-align: middle;
            text-align: center;
        }
    </style>
    {% block css %}
        <!--其他页面CSS样式编写区域-->
    {% endblock %}
</head>
<body class="hold-transition skin-blue sidebar-mini">
    <div class="wrapper">
        <!--1.头部标签区域-->
        <header class="main-header">
            <!--1.1 左侧系统名称-->
            <a href="{{ url_for('admin.index') }}" class="logo">
                <span>
                    <img src="{{ url_for('static',filename='base/images/logo.png') }}"
                         style="height: 40px;width: 40px"/>
                    星空电影系统
                </span>
                <span class="logo-lg">
                    <img src="{{ url_for('static',filename='base/images/logo.png') }}"
                        style="height: 40px;width: 40px"/>
                    电影管理系统
                </span>
            </a>
            <!--1.2 右侧下拉菜单(用户名显示  修改密码  退出系统)-->
            <nav class="navbar navbar-static-top">
                <a href="#" class="sidebar-toggle" data-toggle="offcanvas" rel="button">
                    <span class="sr-only">下拉菜单</span>
                </a>
                <div class="navbar-custom-menu">
                    <ul class="nav navbar-nav">
                         <!--1.2.1 用户名显示以及图像-->
                        <li class="dropdown user user-menu">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                                <img src="{{ url_for('static',filename='admin/dist/img/mtianyan.jpg') }}"
                                    class="user-image" alt="User Image"/>
                                <span class="hidden-xs">{{ session['admin'] }}</span>
                            </a>
                            <!--1.2.1.1 嵌套的列表-->
                            <ul class="dropdown-menu">
                                <li class="user-header">
                                    <img src="{{ url_for('static',filename='admin/dist/img/mtianyan.jpg') }}"
                                        class="img-circle" alt="User Image">
                                    <p>
                                        {{ session['admin'] }}
                                        <small>{{ online_time }}</small>
                                    </p>
                                </li>
                                <!--修改密码和退出系统-->
                                <li class="user-footer">
                                    <div class="pull-left">
                                        <a href="#" class="btn btn-default btn-flat">修改密码</a>
                                    </div>
                                    <div class="pull-right">
                                        <a href="#" class="btn btn-default btn-flat">退出系统</a>
                                    </div>
                                </li>
                            </ul>
                        </li>
                    </ul>
                </div>
            </nav>
        </header>
        <!--2.搜索框-->
        <aside class="main-sidebar">
            <section class="sidebar">
                <div class="user-panel">
                    <div class="pull-left image">
                        <img src="{{ url_for('static',filename='admin/dist/img/mtianyan.jpg') }}"
                             class="img-circle" alt="User Image">
                    </div>
                    <div class="pull-left info">
                        <p>用户{{ session['admin'] }}</p>
                        <a href="#"><i class="fa fa-circle text-success"></i>在线</a>
                    </div>
                </div>
                <!--2.1 搜索框-->
                <form action="#" method="get" class="sidebar-form">
                    <div class="input-group">
                        <input type="text" name="q" class="form-control"
                               placeholder="搜索...">
                        <span class="input-group-btn">
                            <button type="submit" name="search" id="search-btn"
                                    class="btn btn-flat">
                                <i class="fa fa-search"></i>
                            </button>
                        </span>
                    </div>
                </form>
                <!--2.2 添加左侧菜单选项-->
                {% include "admin/grid.html" %}
            </section>
        </aside>
        <!--3.页面主内容-->
        <div class="content-wrapper">
            {% block content %}
            {% endblock %}
        </div>
        <!--4.底部内容-->
        <footer class="main-footer">
            <div class="pull-right hidden-xs">
                <b>星空版本</b>
            </div>
            <strong>版本 2021-2022 <a href="#"></a>mobcute</strong>所有
        </footer>
    </div>
    <!--5.js加载-->
    <script src="{{ url_for('static',filename='admin/plugins/jQuery/jQuery-2.2.0.min.js') }}"></script>
    <script src="{{ url_for('static',filename='admin/bootstrap/js/bootstrap.min.js') }}"></script>
    <script src="{{ url_for('static',filename='admin/plugins/slimScroll/jquery.slimscroll.min.js') }}"></script>
    <script src="{{ url_for('static',filename='admin/plugins/fastclick/fastclick.js') }}"></script>
    <script src="{{ url_for('static',filename='admin/dist/js/app.min.js') }}"></script>
    <script src="{{ url_for('static',filename='admin/dist/js/demo.js') }}"></script>
    <script src="{{ url_for('static',filename='admin/plugins/datepicker/bootstrap-datepicker.js') }}"></script>
    <script src="{{ url_for('static',filename='admin/plugins/datepicker/locales/bootstrap-datepicker.zh-CN.js') }}"></script>
    <script src="http://cdn.bootcss.com/holder/2.9.4/holder.min.js"></script>
    {% block js %}
        <!--加载其他页面的JS文件-->
    {% endblock %}
</body>
</html>

17. 新建grid.html菜单页面

<!--左侧菜单页面-->
<ul class="sidebar-menu">
    <li class="header">菜单管理</li>
    <!--1.首页-->
    <li class="treeview" id="g-1">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>首页</span>
            <span class="label label-primary pull-right">1</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-1-1">
                <a href="{{ url_for('admin.index') }}">
                    <i class="fa fa-circle-o"></i>控制面板
                </a>
            </li>
        </ul>
    </li>
</ul>

18. 修改views.py文件中 添加管理员日志

'''
app/admin/views
管理员模块  视图文件
后台登录系统
'''
# 1.登录功能实现
from flask import render_template,flash,redirect,url_for,session,request
from . import admin
from app.admin.forms import LoginForm
from app.models import Admin,Adminlog
from app.models import db
#1.登录功能实现
@admin.route("/login/",methods=['GET','POST'])
def login():
    #1.获取登录表单
    form=LoginForm()
    # 2.判断是否提交按钮
    if form.validate_on_submit():
        # 3.获取表单数据
        data=form.data
        # 4.判断账号是否一致
        # query查询
        # name缺省值参数
        # data数据{'account':'admin','pwd':'123'}
        # first() 第一个被查询出来的值 将查询出来的数据保存成Admin的实体类
        admin=Admin.query.filter_by(name=data['account']).first()
        # 5.判断密码是否一致
        if admin==None or not admin.check_pwd(data['pwd']):
            # 5.1通过flash发送错误信息
            flash("用户名或密码错误",'err')
            # 5.2 重定向请求
            return redirect(url_for('admin.login'))
        # 6.如果都正确 则保存session
        session['admin']=data['account']
        session['admin_id']=admin.id
        # 7.设置管理员日志
        adminlog = Adminlog(
            admin_id=admin.id,
            ip=request.remote_addr
        )
        # 8.数据库添加session add是数据库添加操作
        db.session.add(adminlog)
        db.session.commit()
        # 9.输出结果
        print("登录成功")
        # 10.重定向
        # 当需要获取前端页面表单传过来的id值的时候,我们需要使用request.args.get
        # request.args.get('next') 获取请求的单个参数
        return redirect(url_for('admin.index'))

    return render_template("admin/login.html",form=form)
# 2.系统首页
@admin.route("/")
def index():
    return render_template("admin/index.html")

        18.1 models中添加管理员日志和管理员操作日志

'''
模型层
跟数据库中表一一对应
'''
# 调用init文件中的db属性
from app import db
from datetime import datetime
# 1.管理员
class Admin(db.Model):
    # 1.设置表格名称(数据库表一致)
    __tablename__='admin'
    # 2.表格是否存在
    __table_args__={'useexisting':True}
    # 3.设置映射
    id = db.Column(db.Integer,primary_key=True)# 编号
    name=db.Column(db.String(100),unique=True)# 管理员账号
    pwd = db.Column(db.String(100))# 管理员密码
    is_super=db.Column(db.SmallInteger)# 是否为超级管理员 0为超级管理员
    role_id=db.Column(db.Integer)# 所属角色
    addtime=db.Column(db.DateTime,index=True,default=datetime.now)
    # '''外键关联'''
    # adminlogs=db.relationship('Adminlog',backref='admin')# 管理员登录日志外键关联
    # oplogs=db.relationship("Oplog",backref='admin')
    # 4.显示对象属性
    def __repr__(self):
        return '<Admin %r>'%self.name
    # 5.检查密码
    def check_pwd(self,pwd):
        # 系统密码
        print("系统密码:",self.pwd)
        # 用户密码
        print("用户密码:",pwd)
        return self.pwd == pwd
# 2.管理员登录日志
class Adminlog(db.Model):
    __tablename__='adminlog'
    __table_args__={'useexisting':True}
    id = db.Column(db.Integer,primary_key=True)# 编号

    admin_id=db.Column(db.Integer,db.ForeignKey('admin.id'))# 管理员编号
    ip=db.Column(db.String(100))# 登录ip
    addtime=db.Column(db.DateTime,index=True,default=datetime)

    def __repr__(self):
        return "<Adminlog %r>"%self.id
# 3.管理员操作日志
class Oplog(db.Model):
    __tablename__='oplog'
    __table_args__={'useexisting':True}
    id = db.Column(db.Integer,primary_key=True)
    admin_id=db.Column(db.Integer,db.ForeignKey('admin.id'))
    ip=db.Column(db.String(100))# ip地址
    reason=db.Column(db.String(600))# 操作原因
    addtime=db.Column(db.DateTime,index=True,default=datetime)

    def __repr__(self):
        return "<Oplog %r>"%self.id

        18.2 login函数中添加管理员登录日志

上个login内已经添加 adminlog表中可以查看管理员登录日志

19. 标签管理-添加标签

    19.1 grid.html中添加标签请求

<!--左侧菜单页面-->
<ul class="sidebar-menu">
    <li class="header">菜单管理</li>
    <!--1.首页-->
    <li class="treeview" id="g-1">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>首页</span>
            <span class="label label-primary pull-right">1</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-1-1">
                <a href="{{ url_for('admin.index') }}">
                    <i class="fa fa-circle-o"></i>控制面板
                </a>
            </li>
        </ul>
    </li>
    <!--2.标签管理-->
    <li class="treeview" id="g-2">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>标签管理</span>
            <span class="label label-primary pull-right">2</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-2-1">
                <a href="{{ url_for('admin.tag_add') }}">
                    <i class="fa fa-circle-o"></i>添加标签
                </a>
            </li>
            <li id="g-2-2">
                <a href="{{url_for('admin.tag_list',page = 1)}}">
                    <i class="fa fa-circle-o"></i>标签列表
                </a>
            </li>
        </ul>
    </li>
</ul>

    19.2 views.py中添加 tag_add函数

# 3.标签管理-添加标签
@admin.route('/tag_add/',methods=['GET','POST'])
def tag_add():
    '''第一种情况:点击左侧菜单子选项  进入到tag_add.html页面
        第二种情况:tag_add.html页面 提交form表单数据保存
    '''
    # 3.1 获取表单验证
    form = TagForm()
    # 3.2 判断是否点击了提交按钮
    if form.validate_on_submit():
        # 获取表单数据
        data = form.data
        # 根据标签名称查找统计标签
        tag = Tag.query.filter_by(name=data['name']).count()
        # 若查找该标签
        if tag == 1:
            flash("标签已经存在,不可重复",'err')
            return redirect(url_for('admin.tag_add'))
        # 没有查找到该标签
        tag = Tag(name=data['name'])
        # 设置session添加
        db.session.add(tag)
        db.session.commit()
        # 添加管理员操作日志
        oplog = Oplog(
            admin_id = session['admin_id'],
            ip = request.remote_addr,
            reason='添加标签%s'%data['name']
        )
        db.session.add(oplog)
        db.session.commit()

        flash("标签添加成功",'ok')
        redirect(url_for('admin.tag_add'))

    return render_template('admin/tag_add.html',form=form)

    19.3 forms.py中添加 TagForm()

# 2.标签的表单
class TagForm(FlaskForm):
    name = StringField(
        label='名称',
        validators=[DataRequired("标签名不能为空")],
        description='电影的标签',
        render_kw={
            'class':'form-control',
            'id' : 'input_name',
            'placeholder':'请输入电影标签名称!!'
        })
    submit = SubmitField(
        '添加',
        render_kw = {'class':'btn btn-primary'}
    )

    19.4 admin文件夹中添加  tag_add.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}

<!--2.设置显示主内容-->
{% block content %}
    <!--内容--->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 标签管理
                </a>
            </li>
        </ol>
    </section>
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border" >
                        <h3 class="box-title">添加标签</h3>
                    </div>
                    <form role="form" method="post" >
                       <div class="box-body">
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--标签设置-->
                            <div class="form-group">
                                <label for="input_name">{{ form.name.label }}</label>

                                {{ form.name }}
                                {% for err in form.name.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                       </div>
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--3.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-2').addClass('active');
            $('#g-2-1').addClass('active');
        });
    </script>
{% endblock %}

    19.5 models.py文件中添加  Tag类

# 4.标签表
class Tag(db.Model):
    __tablename__ = 'tag'
    __table_args__ =  {'useexisting':True}
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(100),unique=True)# 标签名称
    addtime = db.Column(db.DateTime,index=True,default=datetime.now()) # 添加时间

    # 设置外键关联  与 电影的外键关联movie
    movies = db.relationship('Movie',backref='tag')

    # 显示属性
    def __repr__(self):
        return "<Tag %r>"%self.name

20.标签管理-标签列表

    20.1 grid.html中添加标签列表请求

已添加

    20.2 views.py中添加 tag_list函数

# 4.标签管理-标签列表
@admin.route("/tag_list/<int:page>/",methods=['GET'])
def tag_list(page=None):
    '''
        1.点击左侧菜单 标签列表===> tag_list.html页面展示数据
        2.点击页码 使用缺省值参数 page接受页码值===>根据页码查询数据并展示到tag_list.html
    '''
    # 第一种情况无页码
    if page is None:
        page = 1
    # 分页查询
    # paginate(page,per_page,False) 显示第page页 每页per_page,error_out=False不抛出404
    # 按照标签添加时间进行降序 分页插件设置页码
    page_data = Tag.query.order_by(Tag.addtime.desc())\
            .paginate(page=page,per_page=3)
    return render_template("admin/tag_list.html",page_data=page_data)

    20.3 admin文件夹中添加  tag_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.标签列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 标签管理
                </a>
            </li>
            <li class="active">
                标签列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">标签列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>名称</th>
                                    <th>添加时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.name }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>
                                            <a href="{{url_for('admin.tag_edit',id=v.id)}}" class="label label-success">编辑</a>
                                            <a href="{{url_for('admin.tag_del',id=v.id)}}" class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.tag_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-2').addClass('active');
            $('#g-2-2').addClass('active');
        });
    </script>
{% endblock %}

    20.4 新建ui/admin_page.html

<!--分页查询部分 macro相当于模板中声明函数-->
<!--pg.page(page_data,'admin.tag_list')-->
{% macro page(data,url) %}
    {% if data %}
        <ul class="pagination pagination-sm no-margin pull-right">
            <li>
                <a href="{{ url_for(url,page=1) }}">首页</a>
            </li>
            {% if data.has_prev %}
                <li><a href="{{ url_for(url,page=data.prev_num)}}">上一页</a></li>
            {% else %}
                <li class="disabled"><a href="#">上一页</a></li>
            {% endif %}
            {% for v in data.iter_pages() %}
                {% if v %}
                    {% if v == data.page %}
                        <li class="active"><a href="#">{{ v }}</a></li>
                    {% else %}
                        <li><a href="{{ url_for(url,page=v) }}">{{ v }}</a></li>
                    {% endif %}
                {% endif %}
            {% endfor %}

            {% if data.has_next %}
                <li><a href="{{ url_for(url,page=data.next_num) }}">下一页</a></li>
            {% else %}
                <li class="disabled"><a href="#">下一页</a></li>
            {% endif %}
            <li><a href="{{ url_for(url,page=data.pages) }}">尾页</a></li>
        </ul>
    {% endif %}
{% endmacro %}

21.标签管理-标签编辑

    21.1 tag_list.html中发送编辑请求

    21.2 views.py中添加  tag_edit函数

# 5.标签管理-标签编辑
@admin.route("/tag_edit/<int:id>",methods=['GET','POST'])
def tag_edit(id=None):
    # 5.1 获取表单
    form = TagForm()
    # 5.2 将表单中的按钮改成修改
    form.submit.label.text = '修改'
    # 5.3 根据id值查询数据库 有数据或者404 tag是原有的标签数据  喜剧片
    tag = Tag.query.get_or_404(id)
    # 5.4 判断表单是否提交
    if form.validate_on_submit():
        # 5.5 获取表单数据
        data = form.data
        # 5.6 先把用户数据查询一遍判断是否存在
        tag_count = Tag.query.filter_by(name=data['name']).count()
        # 5.7 判断标签是否存在
        if tag.name != data['name'] and tag_count == 1:
            flash("标签名称已经存在",'err')
            return redirect(url_for('admin.tag_edit',id=tag.id))
        # 5.8 表单数据更改
        tag.name = data['name']
        # 5.9 数据库的数据提交和添加
        db.session.add(tag)
        db.session.commit()
        # 5.10 标签的提示框
        flash("标签已经修改成功",'ok')
        # 5.11 重定向到编辑页面
        redirect(url_for('admin.tag_edit',id=tag.id))
    return render_template("admin/tag_edit.html",form=form,tag=tag)

    21.3 admin文件夹下添加  tag_edit.html

<!--1.继承 admin.html-->
{% extends 'admin/admin.html' %}

<!--2.主页面区域-->
{% block content %}
    <!--2.1 页面路径-->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 标签管理
                </a>
            </li>
            <li class="active">
                标签编辑
            </li>
        </ol>
    </section>
    <!--2.2 主内容-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border">
                        <h3 class="box-title">标签编辑</h3>
                    </div>
                    <!--2.2.1 表单-->
                    <form role="form" method="post">
                        <div class="box-body">
                            <!--2.2.2 弹出框-->
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--2.2.3 标签框-->
                            <div class="form-group">
                                <label for="input_name">{{ form.name.label }}</label>
                                {{ form.name(value = tag.name) }}
                                {% for err in form.name.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                        </div>
                        <!--2.2.4 修改按钮和令牌-->
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>

                    </form>
                </div>
            </div>
        </div>
    </section>


{% endblock %}
<!--3.修改左侧菜单页面内容-->
{% block js %}
    <script>
        $(document).ready(function (){
            $('#g-2').addClass('active');
            $('#g-2-2').addClass('active');
        });
    </script>
{% endblock %}

22.标签管理-标签删除

    22.1 tag_list.html中发送编辑请求

    22.2 views.py中添加  tag_del函数

# 6.标签管理-标签删除
@admin.route('/tag_del/<int:id>',methods=['GET'])
def tag_del(id=None):
    # 6.1 查看是否存在该标签
    # filter_by查不到或者多个数据不会报错,get会报错
    tag = Tag.query.filter_by(id=id).first_or_404()
    # 6.2 删除标签
    db.session.delete(tag)
    db.session.commit()
    # 6.3 提示框
    flash("标签<<{0}>>删除成功".format(tag.name),'ok')
    # 6.4 重定向标签列表页面
    return redirect(url_for('admin.tag_list',page=1))

23.电影管理-添加电影

    23.1 grid.html中 设置电影管理  添加电影 和电影列表

<!--3.电影管理-->
    <li class="treeview" id="g-3">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>电影管理</span>
            <span class="label label-primary pull-right">2</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-3-1">
                <a href="{{ url_for('admin.movie_add') }}">
                    <i class="fa fa-circle-o"></i>添加电影
                </a>
            </li>
            <li id="g-3-2">
                <a href="{{url_for('admin.movie_list',page=1)}}">
                    <i class="fa fa-circle-o"></i>电影列表
                </a>
            </li>
        </ul>
    </li>

    23.2 views.py中 添加movie_add和movie_list请求函数


# 7.电影管理-电影添加
@admin.route('/movie_add',methods=['GET','POST'])
def movie_add():
    # 7.1 获取电影表单
    form = MovieForm()
    # 7.2 判断按钮是否点击
    if form.validate_on_submit():
        # 7.3 获取表单数据
        data = form.data
        # 7.4 处理上传文件以及LOGO
        file_url = secure_filename(form.url.data.filename)
        file_logo = secure_filename(form.logo.data.filename)
        # 7.5 判断当前项目中的上传文件目录是否存在 static/uploads文件夹
        if not os.path.exists(app.config['UP_DIR']):
            # 7.5.1 创建目录
            os.makedirs(app.config['UP_DIR'])
            # 7.5.2 更改目录以及目录权限
            os.chmod(app.config['UP_DIR'],'rb')
        # 7.6 修改form表单数据
        # file_url ====>psdb.png  els.mp4
        url = change_filename(file_url)
        logo = change_filename(file_logo)
        # 7.7 保存数据到form表单
        # static/uploads/20220406173106f5a6a528041b429eb0fa50004fc9abea.png
        form.url.data.save(app.config['UP_DIR']+url)
        form.logo.data.save(app.config['UP_DIR']+logo)
        # 7.8 设置form表单数据
        movie = Movie(
            title=data['title'],
            url = url,
            info =data['info'],
            logo = logo,
            star = int(data['star']),
            playnum = 0,
            commentnum = 0,
            tag_id =int(data['tag_id']),
            area=data['area'],
            release_time=data['release_time'],
            length=data['length']
        )
        # 7.9 添加数据
        db.session.add(movie)
        db.session.commit()
        # 7.10 弹出框
        flash("添加电影成功啦!!!",'ok')
        # 7.11 重定向
        return redirect(url_for("admin.movie_add"))
    # 7.12 进入添加页面
    return render_template('admin/movie_add.html',form=form)
def change_filename(filename):
    # 1.将传递的路径进行分解  E:/pycharm/project/els.mp4
    fileinfo = os.path.splitext(filename)
    # 2.拼接新的文件名称
    '''
    2022040617310
        datetime.now()当前时间 按照YYYYmmddHHMMSS
    f5a6a528041b429eb0fa50004fc9abea
        str(uuid.uuid4().hex) 
    fileinfo[-1]
        .png  .mp4
    '''
    filename = datetime.now().strftime("%Y%m%d%H%M%S") + str(uuid.uuid4().hex)+fileinfo[-1]
    return filename

    23.3 forms.py中 添加MovieForm


# 3.电影的表单
class MovieForm(FlaskForm):
    title = StringField(
        label='片名',
        validators=[DataRequired('片名不能为空!')],
        description='片名',
        render_kw={
            'class':'form-control',
            'id':'input_title',
            'placeholder':'请输入片名'
        }
    )
    url = FileField(
        label='文件',
        validators=[DataRequired('请上传文件')],
        description='文件'
    )
    info = TextAreaField(
        label='简介',
        validators=[DataRequired('简介不能为空')],
        description="简介",
        render_kw={
            'class':'form-control',
            'rows':10
        }
    )
    logo = FileField(
        label='封面',
        validators=[DataRequired("请上传封面")],
        description='封面'
    )
    star = SelectField(
        label='星级',
        validators=[DataRequired('请选择星级')],
        coerce=int,
        choices=[(1,'1星'),(2,'2星'),(3,'3星'),(4,'4星'),(5,'5星')],
        description='星级',
        render_kw={
            'class':'form-control'
        }
    )
    tag_id = SelectField(
        label='标签',
        validators=[DataRequired('请选择标签!')],
        coerce=int,
        # 查询数据库中的tag标签表的内容循环遍历
        choices=[(v.id,v.name) for v in Tag.query.all()],
        description='标签',
        render_kw={
            'class':'form-control'
        }
    )
    area = StringField(
        label='地区',
        validators=[
            DataRequired("请输入地区!")
        ],
        description='地区',
        render_kw={
            'class':'form-control',
            'placeholder':'请输入地区'
        }
    )
    length = StringField(
        label='时长',
        validators=[DataRequired('片长不能为空!')],
        description='片长',
        render_kw={
            'class':'form-control',
            'placeholder':'请输入片长!'
        }
    )
    release_time = StringField(
        label='上映时间',
        validators=[DataRequired('上映时间不能为空!')],
        description='上映时间',
        render_kw={
            'class':'form-control',
            'placeholder':'请选择上映时间!',
            'id':'input_release_time'
        }
    )
    submit = SubmitField(
        '添加',
        render_kw= {
            'class':'btn btn-primary'
        }
    )

    23.4 models.py中 添加Movie

        外键关联  Comment  评论   MovieCol收藏

# 5.电影表
class Movie(db.Model):
    __tablename__ = 'movie'
    __table_args__ = {'useexisting':True}
    id = db.Column(db.Integer,primary_key=True)
    title = db.Column(db.String(255),unique=True)
    url = db.Column(db.String(255), unique=True)
    info = db.Column(db.Text)
    logo = db.Column(db.String(255), unique=True)
    star = db.Column(db.SmallInteger)
    playnum = db.Column(db.BigInteger)
    commentnum = db.Column(db.BigInteger)

    tag_id = db.Column(db.Integer,db.ForeignKey('tag.id'))
    area = db.Column(db.String(255))
    release_time = db.Column(db.Date)
    length = db.Column(db.String(100))
    addtime = db.Column(db.DateTime,index=True,default=datetime.now)
    # 评论和收藏暂时不写
    comments= db.relationship('Comment',backref='movie')
    moviecols = db.relationship('Moviecol', backref='movie')

    def __repr__(self):
        return "<Movie %r>"%self.title
    # 设置外键关联  与 电影的外键关联movie
    movies = db.relationship('Movie',backref='tag')

   添加与tag的关联

23.5 admin文件夹中  movie_add.html和 movie_list.html

24.电影管理-电影列表

    24.1 grid.html 添加电影列表请求

    24.2 views.py 添加函数 movie_list

# 8.电影管理-电影列表
@admin.route('/movie_list/<int:page>',methods=['GET'])
def movie_list(page=None):
    # 8.1 判断page是否有值
    if page is None:
        page  = 1
    # 8.2 进行关联查询  关联Tag查询 单表filter_by 多表filter进行关联字段的
    # 过滤条件  Tag.id == Movie.tag_id
    # 排序条件  Movie.addtime.desc()
    # 分页设置  page=page per_page=1 每页显示1条数据 当前页面是那一页
    page_data = Movie.query.join(Tag).filter(
        Tag.id == Movie.tag_id
    ).order_by(
        Movie.addtime.desc()
    ).paginate(page=page,per_page=1)
    # 8.3 返回movie_list.html 将分页数据传递到前端
    return render_template("admin/movie_list.html",page_data=page_data)

    24.3 admin文件夹中新建  movie_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.电影列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 电影管理
                </a>
            </li>
            <li class="active">
                电影列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">电影列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>片名</th>
                                    <th>片长</th>
                                    <th>标签</th>
                                    <th>地区</th>
                                    <th>星级</th>
                                    <th>播放数量</th>
                                    <th>评论数量</th>
                                    <th>上映时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.title }}</td>
                                        <td>{{ v.length }}分钟</td>
                                        <td>{{ v.tag.name }}</td>
                                        <td>{{ v.area }}</td>
                                        <td>{{ v.star }}</td>
                                        <td>{{ v.playnum }}</td>
                                        <td>{{ v.commentnum }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>
                                            <a href="{{ url_for('admin.movie_edit',id=v.id) }}" class="label label-success">编辑</a>
                                            <a href="{{ url_for('admin.movie_del',id=v.id) }}" class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.movie_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-3').addClass('active');
            $('#g-3-2').addClass('active');
        });
    </script>
{% endblock %}

25.电影管理-电影编辑

    25.1 movie_list.html 添加编辑请求

    25.2 views中添加函数  movie_edit

# 9.电影管理-电影编辑
@admin.route("/movie_edit/<int:id>",methods=['GET','POST'])
def movie_edit(id=None):
    # 9.1 获取电影表单
    form = MovieForm()
    form.submit.label.text = '修改'
    # 9.2 设置url,logo非空验证为空 编辑不修改的时候 不会验证器报错
    form.url.validators = []
    form.logo.validators = []
    # 9.3 根据id查询数据
    movie = Movie.query.get_or_404(int(id))
    # 9.4 判断请求类型
    if request.method == "GET":
        # 9.5 将info,tag_id,star数据放到表单中显示在编辑页面
        form.info.data = movie.info
        form.tag_id.data = movie.tag_id
        form.star.data = movie.star
    # 9.6 表单提交 post请求
    if form.validate_on_submit():
        # 9.7 获取表单数据
        data = form.data
        # 9.8 根据表单名查看数据库是否存在
        movie_count = Movie.query.filter_by(title=data['title']).count()
        # 9.9 判断电影名称是否存在以及电影名称没有修改
        if movie_count == 1 and movie.title != data['title']:
            # 提示错误信息
            flash("片名已经存在!",'err')
            return redirect(url_for("admin.movie_edit",id=id))
        # 9.10 创建目录 uploads不存在则新建 存在则不再新建
        if not os.path.exists(app.config['UP_DIR']):
            os.makedirs(app.config['UP_DIR'])
            os.chmod(app.config['UP_DIR'],'rb')
        # 9.11  上传新的视频文件
        if form.url.data != "":
            # 删除原有的视频文件
            os.remove(app.config['UP_DIR'] + movie.url)
            # 上传的视频文件名称
            file_url = secure_filename(form.url.data.filename)
            # 修改了的视频文件名称
            movie.url = change_filename(file_url)
            form.url.data.save(app.config['UP_DIR']+movie.url)


        # 9.12 上传图片
        if form.logo.data != "":
            # 删除原有的图片文件
            os.remove(app.config['UP_DIR']+movie.logo)
            file_logo = secure_filename(form.logo.data.filename)
            movie.logo = change_filename(file_logo)
            form.logo.data.save(app.config['UP_DIR'] + movie.logo)
        # 9.13 设置其他的数据信息
        movie.star = data['star']
        movie.tag_id = data['tag_id']
        movie.info = data["info"]
        movie.title = data['title']
        movie.area = data['area']
        movie.length = data['length']
        movie.release_time = data['release_time']
        # 9.14 数据提交
        db.session.add(movie)
        db.session.commit()
        # 9.15 提示修改成功
        flash("修改电影成功啦啦啦!!!",'ok')
        return redirect(url_for('admin.movie_edit',id=id))

    # 返回到电影编辑页面
    return render_template("admin/movie_edit.html",form=form,movie=movie)

    25.3 admin文件夹中新建  movie_edit.html

<!--1.继承 admin.html-->
{% extends 'admin/admin.html' %}

<!--2.主页面区域-->
{% block content %}
    <!--2.1 页面路径-->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 电影管理
                </a>
            </li>
            <li class="active">
                电影编辑
            </li>
        </ol>
    </section>
    <!--2.2 主内容-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border">
                        <h3 class="box-title">电影编辑</h3>
                    </div>
                    <!--2.2.1 表单-->
                    <form role="form" method="post" enctype="multipart/form-data">
                        <div class="box-body">
                            <!--2.2.2 弹出框-->
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--2.2.3 电影框-->
                            <!--1.片名-->
                            <div class="form-group">
                                <label for="input_title">{{ form.title.label }}</label>
                                {{ form.title(value = movie.title) }}
                                {% for err in form.title.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--2.url-->
                            <div class="form-group">
                                <label for="input_url">{{ form.url.label }}</label>
                                {{ form.url(value = movie.url) }}
                                {% for err in form.url.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                                <div style="margin-top: 5px">
                                    <div id="moviecontainer"></div>
                                </div>
                            </div>
                            <!--3.电影介绍-->
                            <div class="form-group">
                                <label for="input_info">{{ form.info.label }}</label>
                                {{ form.info(value = movie.info) }}
                                {% for err in form.info.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                             <!--4.封面-->
                            <div class="form-group">
                                <label for="input_logo">{{ form.logo.label }}</label>
                                {{ form.logo(value = movie.logo) }}
                                {% for err in form.logo.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                                <img src="{{ url_for('static',filename='uploads/'+movie.logo) }}"
                                    style="margin-top: 5px" class="img-responsive" alt="">

                            </div>
                            <!--5.电影评级-->
                            <div class="form-group">
                                <label for="input_star">{{ form.star.label }}</label>
                                {{ form.star }}
                                {% for err in form.star.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--6.电影标签-->
                            <div class="form-group">
                                <label for="input_tag_id">{{ form.tag_id.label }}</label>
                                {{ form.tag_id }}
                                {% for err in form.tag_id.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--7.上映地区-->
                            <div class="form-group">
                                <label for="input_area">{{ form.area.label }}</label>
                                {{ form.area(value=movie.area) }}
                                {% for err in form.area.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                           <!--8.片长-->
                            <div class="form-group">
                                <label for="input_length">{{ form.length.label }}</label>
                                {{ form.length(value=movie.length) }}
                                {% for err in form.length.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                             <!--9.上映时间-->
                            <div class="form-group">
                                <label for="input_release_time">{{ form.release_time.label }}</label>
                                {{ form.release_time(value=movie.release_time) }}
                                {% for err in form.release_time.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                        </div>
                        <!--2.2.4 修改按钮和令牌-->
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>

                    </form>
                </div>
            </div>
        </div>
    </section>


{% endblock %}
<!--3.修改左侧菜单页面内容-->
{% block js %}
    <!--播放页面-->
    <!--1.加载js文件-->
    <script src="{{ url_for('static',filename='jwplayer/jwplayer.js') }}"></script>
    <!--2.设置播放插件的key值-->
    <script type="text/javascript">
        jwplayer.key = 'P9VTqT/X6TSP4gi/hy1wy23BivBhjdzVjMeOaQ==';
    </script>
    <!--3.设置播放的文件以及形式-->
    <script type="text/javascript">
        jwplayer("moviecontainer").setup({
            flashplayer:"{{ url_for("static",filename="jwplayer/jwplayer.flash.swf") }}",
            playlist:[{
                file:"{{ url_for("static",filename="uploads/"+movie.url)}}",
                title:"{{ movie.title }}"
            }],
            modes:[
                {type:"html5"},
                {type:"flash",
                src:"{{ url_for('static',filename='jwplayer/jwplayer.flash.swf') }}"},
                {type:"downlaod"}],
            skin:{name:"vapor"},
            "playlist.position":"left",
            "playlist.sieze":200,
            height:250,
            width:387
        });
    </script>
    <!--4.设置上映时间的格式-->
    <script>
        $(document).ready(function (){
           $('#iniput_release_time').datepicker({
               autoclose: true,
               format:'yyyy-mm-dd',
               language:'zh-CN'
           });
        });
    </script>


    <script>
        $(document).ready(function (){
            $('#g-3').addClass('active');
            $('#g-3-2').addClass('active');
        });
    </script>
{% endblock %}

26.电影管理-电影删除

    26.1 movie_list.html 添加删除请求

    26.2 views中添加函数  movie_del

# 10.电影管理-电影删除
@admin.route("/movie_del/<int:id>",methods=['GET'])
def movie_del(id=None):
    # 10.1 根据id查询删除的数据是否存在
    movie = Movie.query.get_or_404(id)
    # 10.2 若存在则进行删除操作
    if not movie is None:
        # 删除数据库的电影数据时候 uploads中的文件并没有删除掉
        os.remove(app.config['UP_DIR']+movie.url)
        os.remove(app.config['UP_DIR']+movie.logo)

        db.session.delete(movie)
        db.session.commit()
        # 10.3 提示框
        flash("电影删除成功啦!","ok")
        return redirect(url_for('admin.movie_list',page=1))

27.预告管理-添加预告

    27.1 grid.html 添加预告请求 admin.preview_add

<!--4.预告管理-->
    <li class="treeview" id="g-4">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>预告管理</span>
            <span class="label label-primary pull-right">2</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-4-1">
                <a href="{{ url_for('admin.preview_add') }}">
                    <i class="fa fa-circle-o"></i>添加预告
                </a>
            </li>
            <li id="g-4-2">
                <a href="{{url_for('admin.preview_list',page=1)}}">
                    <i class="fa fa-circle-o"></i>预告列表
                </a>
            </li>
        </ul>
    </li>

    27.2 views.py 新建preview_add函数

# 11.预告管理-预告添加
@admin.route("/preview_add/",methods=['GET','POST'])
def preview_add():
    # 11.1 获取预告表单
    form = PreviewForm()
    # 11.2 判断表单是否点击提交
    if form.validate_on_submit():
        # 11.3 获取添加的数据
        data = form.data
        # 11.4 获取logo的名称
        file_logo = secure_filename(form.logo.data.filename)
        # 11.5 判断是否有uploads文件夹
        if not os.path.exists(app.config['UP_DIR']):
            os.makedirs(app.config['UP_DIR'])
            os.chmod(app.config['UP_DIR'],'rb')
        # 11.6 修改logo的文件名称
        logo = change_filename(file_logo)
        # 11.7 保存logo到form中
        form.logo.data.save(app.config['UP_DIR'] + logo)
        # 11.8 设置其他的预告数据
        preview = Preview(
            title=data['title'],
            logo = logo
        )
        # 11.9 添加数据到数据库中
        db.session.add(preview)
        db.session.commit()
        # 11.10 提示成功
        flash("添加预告成功!",'ok')
        return redirect(url_for("admin.preview_add"))

    return render_template("admin/preview_add.html",form=form)

    27.3 models.py 新建 Preview 模型

# 6.上映预告表
class Preview(db.Model):
    __tablename__ = 'preview'
    __table_args__ = {'useexisting':True}
    # 编号
    id = db.Column(db.Integer,primary_key=True)
    # 标题
    title = db.Column(db.String(255),unique=True)
    # 封面
    logo = db.Column(db.String(255),unique=True)
    # 添加时间
    addtime = db.Column(db.DateTime,index=True,default=datetime.now)


    def __repr__(self):
        return "<Preview %r>"%self.title

    27.4 forms.py 新建  PreviewForm表单

# 4.预告的表单
class PreviewForm(FlaskForm):
    title = StringField(
        label="预告标题",
        validators=[
            DataRequired("预告标题不能为空!")],
        description="上映电影的预告标题",
        render_kw= {
            'class':'form-control',
            'placeholder':'请输入预告标题'
        }
    )
    logo = FileField(
        label="预告封面",
        validators=[DataRequired('预告封面不能为空!')],
        description="预告封面"
    )
    submit = SubmitField(
        "添加预告",
        render_kw={
            'class':'btn btn-primary'
        }
    )

    27.5 admin文件夹下新建  preview_add.html

28.预告管理-预告列表

    28.1 grid.html 添加预告列表请求  admin.preview_list

    28.2 views.py 新建preview_list函数

# 12.预告管理-预告列表
@admin.route("/preview_list/<int:page>",methods=['GET'])
def preview_list(page=None):
    # 12.1 判断page是否为None
    if page is None:
        page = 1
    # 12.2 根据添加时间排序的分页数据
    page_data = Preview.query.order_by(
        Preview.addtime.desc()
    ).paginate(page=page,per_page=1)
    # 12.3 返回分页数据
    return render_template("admin/preview_list.html",page_data=page_data)

    28.3 admin文件夹下编辑 preview_add.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}

<!--2.设置显示主内容-->
{% block content %}
    <!--内容--->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 预告管理
                </a>
            </li>
        </ol>
    </section>
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border" >
                        <h3 class="box-title">添加预告</h3>
                    </div>
                    <form role="form" method="post" enctype="multipart/form-data" >
                       <div class="box-body">
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--1.预告标题-->
                            <div class="form-group">
                                <label for="input_title">{{ form.title.label }}</label>

                                {{ form.title }}
                                {% for err in form.title.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                             <!--2.预告LOGO-->
                            <div class="form-group">
                                <label for="input_logo">{{ form.logo.label }}</label>

                                {{ form.logo }}
                                {% for err in form.logo.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                                <img data-src="holder.js/700*320" style="margin-top: 5px"
                                    class="img-responsive" alt="">
                            </div>
                       </div>
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--3.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-4').addClass('active');
            $('#g-4-1').addClass('active');
        });
    </script>
{% endblock %}

29.预告管理-预告编辑

    29.1 preview_list.html 中添加  编辑请求 admin.preview_edit

    29.2 views.py 中添加 preview_edit函数


# 13.预告管理-预告编辑
@admin.route("/preview_edit/<int:id>",methods=['GET','POST'])
def preview_edit(id=None):
    # 13.1 获取预告表单
    form = PreviewForm()
    form.submit.label.text = "修改"
    # 13.2 设置logo的验证器为空
    form.logo.validators = []
    # 13.3 根据id获取预告的数据信息
    preview = Preview.query.get_or_404(int(id))
    # 13.4 判断请求类型
    if request.method == 'GET':
        form.title.data = preview.title
    # 13.5 post请求
    if form.validate_on_submit():
        # 13.6 获取编辑页面的数据
        data = form.data
        # 13.7 判断logo是否为空
        if form.logo.data != "":
            # 13.8 删除原有的封面图片
            os.remove(app.config['UP_DIR']+preview.logo)
            # 13.9 获取上传图片的文件名以及路径
            file_logo = secure_filename(form.logo.data.filename)
            # 13.10 对上传的图片名进行更改
            preview.logo = change_filename(file_logo)
            # 13.11 保存新的数据到form表单中
            form.logo.data.save(app.config['UP_DIR'] + preview.logo)
        # 13.12 设置提交到数据库的数据信息
        preview.title = data['title']
        # 13.13 提交到数据库中
        db.session.add(preview)
        db.session.commit()
        # 13.14 提示框
        flash("预告修改成功!!!",'ok')
        return  redirect(url_for('admin.preview_edit',id=id))

    return  render_template("admin/preview_edit.html",form=form,preview=preview)

    29.3 admin文件夹下编辑preview_edit.html

<!--1.继承 admin.html-->
{% extends 'admin/admin.html' %}

<!--2.主页面区域-->
{% block content %}
    <!--2.1 页面路径-->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 预告管理
                </a>
            </li>
            <li class="active">
                预告编辑
            </li>
        </ol>
    </section>
    <!--2.2 主内容-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border">
                        <h3 class="box-title">预告编辑</h3>
                    </div>
                    <!--2.2.1 表单-->
                    <form role="form" method="post" enctype="multipart/form-data">
                        <div class="box-body">
                            <!--2.2.2 弹出框-->
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--1.预告标题-->
                            <div class="form-group">
                                <label for="input_title">{{ form.title.label }}</label>
                                {{ form.title }}
                                {% for err in form.title.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--2.预告封面-->
                            <div class="form-group">
                                <label for="input_logo">{{ form.logo.label }}</label>
                                {{ form.logo }}
                                {% for err in form.logo.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                                <img src="{{ url_for('static',filename='uploads/'+preview.logo) }}"
                                    style="margin-top: 5px" class="img-responsive" alt="">
                            </div>

                        </div>
                        <!--2.2.4 修改按钮和令牌-->
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>

                    </form>
                </div>
            </div>
        </div>
    </section>


{% endblock %}
<!--3.修改左侧菜单页面内容-->
{% block js %}
    <script>
        $(document).ready(function (){
            $('#g-4').addClass('active');
            $('#g-4-2').addClass('active');
        });
    </script>
{% endblock %}

30.预告管理-预告删除

    30.1 preview_list.html 中添加 删除请求  admin.preview_del

    30.2 views.py 中添加preview_del函数

# 14.预告管理-预告删除
@admin.route("/preview_del/<int:id>",methods=['GET'])
def preview_del(id =None):
    # 14.1 根据id获取预告数据
    preview = Preview.query.get_or_404(id)
    # 14.2 判断是否有数据
    if not preview is None:
        # 14.3 删除原有的预告封面
        os.remove(app.config['UP_DIR']+preview.logo)
        # 14.4 删除数据
        db.session.delete(preview)
        db.session.commit()
        # 14.5 提示删除成功
        flash("预告删除成功啦!!!",'ok')
        return redirect(url_for("admin.preview_list",page=1))
    else:
        flash("预告删除失败啦!!!",'err')
        return redirect(url_for("admin.preview_list",page=1))

31.会员管理-会员列表

    31.1 grid.html 设置会员管理  子标签  会员列表 admin.user_list

 <!--5.会员管理-->
    <li class="treeview" id="g-5">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>会员管理</span>
            <span class="label label-primary pull-right">1</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-5-1">
                <a href="{{ url_for('admin.user_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>会员列表
                </a>
            </li>
        </ul>
    </li>

    31.2 models.py 新建 User


# 7.会员表
class User(db.Model):
    __tablename__ = 'user'
    __table_args__ = {'useexisting': True}
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), unique=True)
    pwd = db.Column(db.String(100))
    email=db.Column(db.String(100),unique=True)
    phone=db.Column(db.String(11),unique=True)
    info = db.Column(db.Text)
    face = db.Column(db.String(255), unique=True)
    addtime = db.Column(db.DateTime, index=True, default=datetime.now)  # 添加时间
    uuid=db.Column(db.String(255),unique=True)# 唯一标识符
    comments=db.relationship('Comment',backref='user')
    moviecols = db.relationship('Moviecol', backref='user')
    # 会员日志、评论表、收藏表外键关联
    def __repr__(self):
        return "<User %r>" % self.name
    def check_pwd(self,pwd):
        # 加密判断
        return pwd == self.pwd

    31.3views.py中 新建 user_list函数

# 15.会员管理-会员列表
@admin.route("/user_list/<int:page>",methods=['GET'])
def user_list(page=None):
    # 15.1 判断page是否为None
    if page is None:
        page = 1
    # 15.2 根据添加时间排序的分页数据
    page_data = User.query.order_by(
        User.addtime.desc()
    ).paginate(page=page,per_page=1)
    # 15.3 返回分页数据
    return render_template("admin/user_list.html",page_data=page_data)

31.5 admin文件夹下 新建user_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.会员列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 会员管理
                </a>
            </li>
            <li class="active">
                会员列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">会员列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>昵称</th>
{#                                    <th>密码</th>#}
                                    <th>电子邮箱</th>
                                    <th>电话号码</th>
                                    <th>头像</th>
                                    <th>状态</th>
                                    <th>注册时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.name }}</td>
{#                                        <td>{{ v.pwd }}</td>#}
                                        <td>{{ v.email }}</td>
                                        <td>{{ v.phone }}</td>
{#                                        <td>{{ v.info }}</td>#}
                                        <td>
                                            {% if v.face %}
                                                <img alt="50*50"
                                                     src="{{ url_for('static',filename='uploads/users/'+v.face) }}"
                                                    class="img-circle"
                                                    style="border: 1px solid #abcdef;width: 50px;">
                                            {% else %}
                                                <img alt="50*50"
                                                     data-src="holder.js/50*50"
                                                    class="img-circle"
                                                    style="border: 1px solid #abcdef;width: 50px;">
                                            {% endif %}
                                        </td>
                                        <td>正常/冻结</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>
                                            <a class="label label-success" href="{{ url_for('admin.user_view',id=v.id,fp=page_data.page) }}">查看</a>
                                            <a class="label label-info">解冻</a>
                                            <a class="label label-warning">冻结</a>
                                            <a href="{{ url_for('admin.user_del', id=v.id,fp=page_data.page)}}" class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.user_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-5').addClass('active');
            $('#g-5-1').addClass('active');
        });
    </script>
{% endblock %}

32.会员管理-会员删除

    32.1 user_list.html 添加 会员删除请求  admin.user_del

    32.2 views.py 新建  user_del函数

# 14.会员管理-会员删除
@admin.route("/user_del/<int:id>",methods=['GET'])
def user_del(id =None):
    form_page= int(request.args.get("fp"))-1
    if not form_page:
        form_page=1
    # 14.1 根据id获取预告数据
    user = User.query.get_or_404(int(id))

    # 14.4 删除数据
    db.session.delete(user)
    db.session.commit()
        # 14.5 提示删除成功
    flash("会员删除成功啦!!!",'ok')
    return redirect(url_for("admin.user_list",page=form_page))

33.会员管理-会员查看

    33.1 user_list.html 添加 会员查看请求  admin.user_view

    33.2 views.py 新建  user_view函数

# 17.会员管理-会员查看
@admin.route("/user_view/<int:id>",methods=['GET'])
def user_view(id=None):
    #17.1
    form_page=request.args.get('fp')
    if not form_page:
        form_page=1
    user=User.query.get_or_404(int(id))
    return render_template("admin/user_view.html",user=user,form_page=form_page)

    33.3 admin文件夹下新建  user_view.html

{% extends 'admin/admin.html' %}

{% block css %}
    <style>
        * {font-family: "Microsoft YaHei";}
        .table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{
            vertical-align: middle;
            text-align: left;
        }
        .td_bd {
            width: 100px;
            font-weight: bold;
        }
    </style>
{% endblock %}


{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统</h1>
        <ol class="breakcrumb">
            <li>
                <a href="{{ url_for('admin.user_list',page=form_page) }}">
                    <i class="fa fa-dashboard"></i>会员管理
                </a>
            </li>
        </ol>
    </section>
    <section class="content" id ="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">会员详情</h3>
                    </div>
                    <div class="box-body table-responsive no-padding">
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <td class="td_bd">编号:</td>
                                    <td>{{ user.id }}</td>
                                </tr>
                                <tr>
                                    <td class="td_bd">昵称:</td>
                                    <td>{{ user.name }}</td>
                                </tr>
                                <tr>
                                    <td class="td_bd">邮箱:</td>
                                    <td>{{ user.email }}</td>
                                </tr>
                                <tr>
                                    <td class="td_bd">手机:</td>
                                    <td>{{ user.phone }}</td>
                                </tr>
                                <tr>
                                    <td class="td_bd">头像:</td>
                                    <td>
                                        {% if user.face %}
                                            <img alt="100*100"
                                                 src="{{ url_for('static',filename='uploads/users/'+user.face)}}"
                                                 class="img-responsive"
                                                 style="border: 1px solid #abcdef;width:100px">
                                        {% else %}
                                            <img alt="100*100"
                                                 data-src="holder.js/100*100"
                                                 class="img-responsive"
                                                 style="border: 1px solid #abcdef;width:100px">
                                        {% endif %}
                                    </td>
                                </tr>
                                <tr>
                                    <td class="td_bd">注册时间:</td>
                                    <td>{{ user.addtime }}</td>
                                </tr>
                                <tr>
                                    <td class="td_bd">唯一标识符:</td>
                                    <td>{{ user.uuid }}</td>
                                </tr>
                                <tr>
                                    <td class="td_bd">个性简介:</td>
                                    <td>{{ user.info }}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </section>
{% endblock %}

{% block js %}
    <script>
        $(document).ready(function (){
            $('#g-5').addClass('active')
            $('#g-5-1').addClass('active')
        });
    </script>
{% endblock %}

34.评论管理-评论列表

    34.1 grid.html新建评论管理 以及评论列表请求  comment_list

<!--6.评论管理-->
    <li class="treeview" id="g-6">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>评论管理</span>
            <span class="label label-primary pull-right">1</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-6-1">
                <a href="{{ url_for('admin.comment_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>评论列表
                </a>
            </li>
        </ul>
    </li>

    34.2 models.py 新建comment类

# 8.评论表
class Comment(db.Model):
    __tablename__='comment'
    __table_args__={'useexisting':True}
    id=db.Column(db.Integer,primary_key=True)
    content=db.Column(db.Text)
    #外键关联
    movie_id=db.Column(db.Integer,db.ForeignKey('movie.id'))
    user_id=db.Column(db.Integer,db.ForeignKey('user.id'))
    addtime=db.Column(db.DateTime,index=True,default=datetime.now)

    def __repr__(self):
        return "<Comment %r>"%self.id

    34.3 views.py 新建comment_list函数

# 18.评论管理-评论列表
@admin.route("/comment_list/<int:page>",methods=['GET'])
def comment_list(page=None):
    #18.1
    if page is None:
        page=1
    #18.2 通过评论join查询相关的movie以及user表
    page_data=Comment.query.join(
        Movie).join(
        User).filter(
        Movie.id==Comment.movie_id,
        User.id==Comment.user_id).order_by(
        Comment.addtime.desc()
    ).paginate(page=page,per_page=1)
    return render_template("admin/comment_list.html",page_data=page_data)

    34.4 admin文件夹下新建 comment_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.评论列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 评论管理
                </a>
            </li>
            <li class="active">
                评论列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border" >
                        <h3 class="box-title">评论列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body box-comments">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        {% for v in page_data.items %}
                        <div class="box-comment">
                            {% if v.user.face %}
                                <img atl="50*50"
                                     src="{{ url_for('static',filename='uploads/users/'+v.user.face) }}"
                                     class="img-circle img-sm"
                                     style="border:1px solid #abcdef;width:50px">
                            {% else %}
                                <img atl="50*50"
                                     data-src="holder.js/50*50"
                                     class="img-circle img-sm"
                                     style="border:1px solid #abcdef;width:50px">
                            {% endif %}
                            <div class="comment-text">
                                <span class="username">
                                    {{ v.user.name }}
                                    <span class="text-muted pull-right">
                                        <i class="fa fa-calendar" aria-hidden="true"></i>
                                        {{ v.addtime }}
                                    </span>
                                </span>
                                关于电影<a>《{{ v.movie.title }}》</a>的评论:{{ v.content|safe }}
                                <br><a href="{{ url_for('admin.comment_del', id=v.id,fp=page_data.page) }}"
                                       class="label label-danger pull-right">删除</a>
                            </div>
                        </div>
                    {% endfor %}
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.comment_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-6').addClass('active');
            $('#g-6-1').addClass('active');
        });
    </script>
{% endblock %}

35.评论管理-评论删除

    35.1 comment_list.html 添加评论删除请求  comment_del

    35.2 views.py 添加 comment_del函数

# 19.评论管理-评论删除
@admin.route("/comment_del/<int:id>",methods=['GET'])
def comment_del(id =None):
    form_page= int(request.args.get("fp"))-1
    if not form_page:
        form_page=1
    # 14.1 根据id获取预告数据
    comment = Comment.query.get_or_404(int(id))
    # 14.4 删除数据
    db.session.delete(comment)
    db.session.commit()
        # 14.5 提示删除成功
    flash("评论删除成功啦!!!",'ok')
    return redirect(url_for("admin.comment_list",page=form_page))

36.收藏管理-收藏列表

    36.1 grid.html 新建收藏管理 admin.moviecol_list

<!--7.收藏管理-->
    <li class="treeview" id="g-7">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>收藏管理</span>
            <span class="label label-primary pull-right">1</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-7-1">
                <a href="{{ url_for('admin.moviecol_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>收藏列表
                </a>
            </li>
        </ul>
    </li>

    36.2 models.py 添加  Moviecol类

        movie.id  user.id

# 9.收藏表
class Moviecol(db.Model):
    __tablename__='moviecol'
    __table_args__={'useexisting':True}
    id=db.Column(db.Integer,primary_key=True)
    #外键关联
    movie_id=db.Column(db.Integer,db.ForeignKey('movie.id'))
    user_id=db.Column(db.Integer,db.ForeignKey('user.id'))
    addtime=db.Column(db.DateTime,index=True,default=datetime.now)

    def __repr__(self):
        return "<Moviecol %r>"%self.id

    36.3 views.py 添加 moviecol_list函数

# 20.收藏管理-收藏列表
@admin.route("/moviecol_list/<int:page>",methods=['GET'])
def moviecol_list(page=None):
    #20.1
    if page is None:
        page=1
    #20.2 通过评论join查询相关的movie以及user表
    page_data=Moviecol.query.join(
        Movie).join(
        User).filter(
        Movie.id==Moviecol.movie_id,
        User.id==Moviecol.user_id).order_by(
        Moviecol.addtime.desc()
    ).paginate(page=page,per_page=1)
    print(page_data)
    return render_template("admin/moviecol_list.html",page_data=page_data)

    36.4 admin文件夹新建  moviecol_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.收藏列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 收藏管理
                </a>
            </li>
            <li class="active">
                收藏列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">收藏列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>电影</th>
                                    <th>用户</th>
                                    <th>收藏时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.movie.title }}</td>
                                        <td>{{ v.user.name }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>
                                            <a href="{{url_for('admin.moviecol_del',id=v.id,fp=page_data.page)}}" class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.moviecol_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-7').addClass('active');
            $('#g-7-1').addClass('active');
        });
    </script>
{% endblock %}

37.收藏管理-收藏删除

    37.1 moviecol_list.html中添加 删除请求 admin.moviecol_del

    37.2 views.py 添加moviecol_del函数

# 21.收藏管理-收藏删除
@admin.route("/moviecol_del/<int:id>",methods=['GET'])
def moviecol_del(id =None):
    form_page= int(request.args.get("fp"))-1
    if not form_page:
        form_page=1
    # 21.1 根据id获取预告数据
    moviecol = Moviecol.query.get_or_404(int(id))
    # 21.4 删除数据
    db.session.delete(moviecol)
    db.session.commit()
        # 14.5 提示删除成功
    flash("收藏删除成功啦!!!",'ok')
    return redirect(url_for("admin.comment_list",page=form_page))

38.日志管理

 38.1 grid.html中

<!--8.日志管理-->
    <li class="treeview" id="g-8">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>日志管理</span>
            <span class="label label-primary pull-right">3</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-8-1">
                <a href="{{ url_for('admin.oplog_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>操作日志列表
                </a>
            </li>
        </ul>
        <ul class="treeview-menu">
            <li id="g-8-2">
                <a href="{{ url_for('admin.adminlog_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>管理员登录日志列表
                </a>
            </li>
        </ul>
        <ul class="treeview-menu">
            <li id="g-8-3">
                <a href="{{ url_for('admin.userlog_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>会员登录日志列表
                </a>
            </li>
        </ul>

    </li>


38.2 models.py编写Userlog , Adminlog , 0plog

# 2.管理员登录日志
class Adminlog(db.Model):
    __tablename__ = 'adminlog'
    __table_args__ = {'useexisting':True}
    id = db.Column(db.Integer,primary_key=True)# 编号
    admin_id = db.Column(db.Integer,db.ForeignKey('admin.id'))# 管理员编号
    ip = db.Column(db.String(100)) # 登录ip
    addtime = db.Column(db.DateTime,index=True,default=datetime.now())# 登录时间

    def __repr__(self):
        return "<Adminlog %r>"%self.id
# 3.管理员操作日志
class Oplog(db.Model):
    __tablename__ = 'oplog'
    __table_args__ = {'useexisting':True}
    id = db.Column(db.Integer,primary_key=True)
    admin_id = db.Column(db.Integer,db.ForeignKey("admin.id"))
    ip = db.Column(db.String(100)) # ip地址
    reason = db.Column(db.String(100))# 操作原因
    addtime = db.Column(db.DateTime,index=True,default=datetime.now())

    def __repr__(self):
        return "<Oplog %r>"%self.id


#10.会员登录日志
class Userlog(db.Model):
    __tablename__='userlog'
    __table_args__={'useexisting':True}
    id=db.Column(db.Integer,primary_key=True)
    user_id=db.Column(db.Integer,db.ForeignKey('user.id'))
    ip=db.Column(db.String(100))
    addtime=db.Column(db.DateTime,index=True,default=datetime.now)
    def __repr__(self):
        return "<Userlog %r>"%self.id


38.3 views.py中添加userlog_list adminlog_list oplog_list函数


# 22. 日志管理-操作日志列表
@admin.route("/oplog_list/<int:page>",methods=['GET'])
def oplog_list(page=None):
    #22.1
    if page is None:
        page=1
    #22.2 oplog关联查询
    page_data=Oplog.query.join(Admin).filter(
        Admin.id==Oplog.admin_id,
    ).order_by(
        Oplog.addtime.desc()
    ).paginate(page=page,per_page=2)
    return render_template("admin/oplog_list.html",page_data=page_data)

#23.日志管理-管理员登录日志列表
@admin.route("/adminlog_list/<int:page>",methods=['GET'])
def adminlog_list(page=None):
    #23.1判断是否
    if page is None:
        page=1
    #23.2
    page_data=Adminlog.query.join(Admin).filter(
        Admin.id==Adminlog.admin_id
    ).order_by(
        Adminlog.addtime.desc()
    ).paginate(page=page,per_page=50)
    return render_template("admin/adminlog_list.html",page_data=page_data)

#24.日志管理-会员登录日志列表
@admin.route("/userlog_list/<int:page>",methods=['GET'])
def userlog_list(page=None):
    #24.1判断是否
    if page is None:
        page=1
    #24.2
    page_data=Userlog.query.join(User).filter(
        User.id==Userlog.user_id
    ).order_by(
        Userlog.addtime.desc()
    ).paginate(page=page,per_page=5)
    return render_template("admin/userlog_list.html",page_data=page_data)


38.4 admin文什夹中 userlog_list.html, adminlog_list.html, oplog_list.html

userlog_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.会员登录日志列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 会员登录日志管理
                </a>
            </li>
            <li class="active">
                会员登录日志列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">会员登录日志列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>会员</th>
                                    <th>登录时间</th>
                                    <th>IP地址</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.user.name }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>{{ v.ip }}</td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.userlog_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-8').addClass('active');
            $('#g-8-3').addClass('active');
        });
    </script>
{% endblock %}

admin_lists.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.管理员登录日志列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 管理员登录日志管理
                </a>
            </li>
            <li class="active">
                管理员登录日志列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">管理员登录日志列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>管理员</th>
                                    <th>登录时间</th>
                                    <th>IP地址</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.admin.name }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>{{ v.ip }}</td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.adminlog_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-8').addClass('active');
            $('#g-8-2').addClass('active');
        });
    </script>
{% endblock %}

oplog_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.操作日志列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 操作日志管理
                </a>
            </li>
            <li class="active">
                操作日志列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">操作日志列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>管理员</th>
                                    <th>操作时间</th>
                                    <th>操作原因</th>
                                    <th>IP地址</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.admin.name }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>{{ v.reason }}</td>
                                        <td>{{ v.ip }}</td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.oplog_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-8').addClass('active');
            $('#g-8-1').addClass('active');
        });
    </script>
{% endblock %}

39.权限管理

    39.1 grid.html 添加权限管理

<!--9.权限管理-->
    <li class="treeview" id="g-9">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>权限管理</span>
            <span class="label label-primary pull-right">2</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-9-1">
                <a href="{{ url_for('admin.auth_add') }}">
                    <i class="fa fa-circle-o"></i>权限添加
                </a>
            </li>
        </ul>
        <ul class="treeview-menu">
            <li id="g-9-2">
                <a href="{{ url_for('admin.auth_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>权限列表
                </a>
            </li>
        </ul>
    </li>

    39.2 models.py 编写 Auth模型

#10.权限
class Auth(db.Model):
    __tablename__='auth'
    __table_args__={'useexisting':True}
    id=db.Column(db.Integer,primary_key=True)
    name=db.Column(db.String(100),unique=True)
    url = db.Column(db.String(255), unique=True)
    # role_id=db.Column(db.Integer,db.ForeignKey('role.id'))
    addtime=db.Column(db.DateTime,index=True,default=datetime.now)
    # roles=db.relationship("Role",backref='auth')
    def __repr__(self):
        return "<Auth %r>"%self.name

    39.3 forms.py 添加  AuthForm表单

# 5.权限得表单
class AuthForm(FlaskForm):
    name=StringField(
        label='权限名称',
        validators=[DataRequired('权限名称不能为空')],
        description='权限名称',
        render_kw={
            'class':'form-control',
            'placeholder':'请输入权限名称'
        }
    )
    url=StringField(
        label='权限地址',
        validators=[DataRequired('权限地址不能为空')],
        description='权限地址',
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入权限地址'
        }
    )
    submit=SubmitField(
        '添加',
        render_kw={
            'class':'btn btn-primary'
        }
    )

    39.4 views.py添加 auth_add,auth_list,auth_edit,auth_del

auth_add,

#25.权限管理-权限添加
@admin.route("/auth_add/",methods=['GET','POST'])
def auth_add():
    form=AuthForm()
    if form.validate_on_submit():
        data=form.data
        auth=Auth(
            name=data['name'],
            url=data['url']
        )
        db.session.add(auth)
        db.session.commit()
        flash("权限添成功",'ok')
    return render_template("admin/auth_add.html",form=form)

auth_list,

#26.日志管理-会员登录日志列表
@admin.route("/auth_list/<int:page>",methods=['GET'])
def auth_list(page=None):
    #26.1判断是否
    if page is None:
        page=1
    #26.2
    page_data=Auth.query.order_by(
        Auth.addtime.desc()
    ).paginate(page=page,per_page=1)
    return render_template("admin/auth_list.html",page_data=page_data)

auth_edit,

#27.权限管理-权限编辑
@admin.route("/auth_edit/<int:id>",methods=['GET','POST'])
def auth_edit(id=None):
    form=AuthForm()
    auth=Auth.query.get_or_404(id)
    form.submit.label.text='编辑'
    if form.validate_on_submit():
        data=form.data
        auth.url=data['url']
        auth.name=data['name']
        db.session.add(auth)
        db.session.commit()
        flash("修改权限成功",'ok')
        redirect(url_for('admin.auth_edit',id=id))
    return render_template("admin/auth_edit.html",form=form,auth=auth)

auth_del

#28.权限管理-权限删除
@admin.route("/auth_del/<int:id>",methods=['GET'])
def auth_del(id=None):
    auth=Auth.query.filter_by(id=id).first_or_404()
    db.session.delete(auth)
    db.session.commit()
    flash("删除权限成功!",'ok')
    return redirect(url_for("admin.auth_list",page=1))

    39.5 admin文件夹中添加  auth_add.html,auth_list.html,auth_edit.html

auth_add.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}

<!--2.设置显示主内容-->
{% block content %}
    <!--内容--->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 权限管理
                </a>
            </li>
        </ol>
    </section>
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border" >
                        <h3 class="box-title">添加权限</h3>
                    </div>
                    <form role="form" method="post" >
                       <div class="box-body">
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--1.权限名称-->
                            <div class="form-group">
                                <label for="input_name">{{ form.name.label }}</label>

                                {{ form.name }}
                                {% for err in form.name.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--2.权限url-->
                            <div class="form-group">
                                <label for="input_url">{{ form.url.label }}</label>

                                {{ form.url }}
                                {% for err in form.url.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                       </div>
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--3.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-9').addClass('active');
            $('#g-9-1').addClass('active');
        });
    </script>
{% endblock %}

,auth_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.权限列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 权限管理
                </a>
            </li>
            <li class="active">
                权限列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">权限列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>名称</th>
                                    <th>地址</th>
                                    <th>添加时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.name }}</td>
                                        <td>{{ v.url }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>
                                            <a href="{{ url_for('admin.auth_edit',id=v.id) }}" class="label label-success">编辑</a>
                                            <a href="{{ url_for('admin.auth_del',id=v.id) }}" class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.auth_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-9').addClass('active');
            $('#g-9-2').addClass('active');
        });
    </script>
{% endblock %}

,auth_edit.html

<!--1.继承 admin.html-->
{% extends 'admin/admin.html' %}

<!--2.主页面区域-->
{% block content %}
    <!--2.1 页面路径-->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 权限管理
                </a>
            </li>
            <li class="active">
                权限编辑
            </li>
        </ol>
    </section>
    <!--2.2 主内容-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border">
                        <h3 class="box-title">权限编辑</h3>
                    </div>
                    <!--2.2.1 表单-->
                    <form role="form" method="post">
                        <div class="box-body">
                            <!--2.2.2 弹出框-->
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--2.2.3 权限框-->
                            <div class="form-group">
                                <label for="input_name">{{ form.name.label }}</label>
                                {{ form.name(value = auth.name) }}
                                {% for err in form.name.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--2.2.4 权限框-->
                            <div class="form-group">
                                <label for="input_name">{{ form.url.label }}</label>
                                {{ form.url(value = auth.url) }}
                                {% for err in form.url.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                        </div>
                        <!--2.2.4 修改按钮和令牌-->
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>

                    </form>
                </div>
            </div>
        </div>
    </section>


{% endblock %}
<!--3.修改左侧菜单页面内容-->
{% block js %}
    <script>
        $(document).ready(function (){
            $('#g-9').addClass('active');
            $('#g-9-2').addClass('active');
        });
    </script>
{% endblock %}

40.角色管理

    40.1 grid.html 添加角色管理

<!--10.角色管理-->
    <li class="treeview" id="g-10">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>角色管理</span>
            <span class="label label-primary pull-right">2</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-10-1">
                <a href="{{ url_for('admin.role_add') }}">
                    <i class="fa fa-circle-o"></i>角色添加
                </a>
            </li>
        </ul>
        <ul class="treeview-menu">
            <li id="g-10-2">
                <a href="{{ url_for('admin.role_list',page=1) }}">
                    <i class="fa fa-circle-o"></i>角色列表
                </a>
            </li>
        </ul>
    </li>

    40.2 models.py 编写Role模型

#11.角色
class Role(db.Model):
    __tablename__='role'
    __table_args__={'useexisting':True}
    id=db.Column(db.Integer,primary_key=True)
    name=db.Column(db.String(100),unique=True)
    # auths = db.Column(db.String(600),db.ForeignKey('auth.id'))
    auths=db.Column(db.String(600))
    addtime=db.Column(db.DateTime,index=True,default=datetime.now)
    admins = db.relationship('Admin', backref='role')  # 管理员外键关联
    # auths=db.relationship('Auth',backref='role')
    def __repr__(self):
        return "<Role %r>"%self.name

    40.3 forms.py 添加RoleForm表单

# 6.角色的表单
class RoleForm(FlaskForm):
    name=StringField(
        label='角色名称',
        validators=[DataRequired('角色名称不能为空')],
        description='角色名称',
        render_kw={
            'class':'form-control',
            'placeholder':'请输入角色名称'
        }
    )
    auths=SelectMultipleField(
        label='权限列表',
        validators=[DataRequired("权限列表不能为空!")],
        # 动态数据填充选择栏  列表生成器
        coerce=int,
        choices=[(v.id,v.name) for v in Auth.query.all()],
        description='权限列表',
        render_kw={
            'class':'form-control'
        }
    )
    submit=SubmitField(
        '添加',
        render_kw={
            'class':'btn btn-primary'
        }
    )

    40.4 views.py添加  role_add,role_list,role_edit,role_del

role_add

#29.角色管理-角色添加
@admin.route("/role_add",methods=['GET','POST'])
def role_add():
    #29.1
    form=RoleForm()
    #29.2 判断表单中按钮是否点击
    if form.validate_on_submit():
        #29.3 获取表单数据
        data=form.data
        role=Role(
            name=data['name'],
            auths=','.join(map(lambda v:str(v),data['auths']))
        )
        db.session.add(role)
        db.session.commit()
        flash("添加角色成功!",'ok')
    return render_template("admin/role_add.html",form=form)

,role_list,


#30.角色管理-角色列表
@admin.route("/role_list/<int:page>",methods=['GET'])
def role_list(page=None):
    #30.1判断是否page为none
    if page is None:
        page=1
    #30.2 查询并分页数据
    page_data=Role.query.order_by(
        Role.addtime.desc()
    ).paginate(page=page,per_page=1)
    '''角色权限显示权限名称'''
    for v in page_data.items:
        # 设置显示的字符串
        auths_str=''
        #auths
        if v.auths:
            # 对权限列表字段值进行切割 返回列表['3','6','7']
            ah_list=v.auths.split(',')
            # 循环遍历权限列表值
            for ix in ah_list:
                #根据id查询auth权限表中的名称数据
                ah=Auth.query.filter_by(id=int(ix)).first_or_404()
                #添加数据
                auths_str+=ah.name+','
        else:
            auths_str='无任何权限'
        # 将需要显示的数据设置到分页数据中
        v.auths=auths_str
    return render_template("admin/role_list.html",page_data=page_data)

role_edit


#31.角色管理-角色编辑
@admin.route("/role_edit/<int:id>",methods=['GET','POST'])
def role_edit(id=None):
    form=RoleForm()
    role=Role.query.get_or_404(id)
    form.submit.label.text='修改'
    if request.method=='GET' and role.auths:
        auths=role.auths
        form.auths.data=list(map(lambda v:int(v),auths.split(',')))
    # 31.5 判断表单是否点击了按钮
    if form.validate_on_submit():
        #31.5.2
        data=form.data
        #31.5.2
        role.name=data['name']
        #31.5.3 根据权限值设置 添加的权限列表值
        role.auths=','.join(map(lambda v:str(v),data['auths']))
        db.session.add(role)
        db.session.commit()
        flash('修改角色成功了!','ok')
    return render_template("admin/role_edit.html",form=form,role=role)

role_del   

#32.角色管理-角色删除
@admin.route("/role_del/<int:id>",methods=['GET'])
def role_del(id=None):
    role=Role.query.filter_by(id=id).first_or_404()
    db.session.delete(role)
    db.session.commit()
    flash("删除角色成功!",'ok')
    return redirect(url_for("admin.role_list",page=1))

40.5 admin文件夹中添加role_add.html,role_list.html,role_edit.html

role_add.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}

{% block css %}
    <style>
        #auth_list.col-md-12,#auth_list{
            padding: 0px;
        }
    </style>


{% endblock %}

<!--2.设置显示主内容-->
{% block content %}
    <!--内容--->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 角色管理
                </a>
            </li>
        </ol>
    </section>
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border" >
                        <h3 class="box-title">添加角色</h3>
                    </div>
                    <form role="form" method="post" >
                       <div class="box-body">
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--角色设置-->
                            <div class="form-group">
                                <label for="input_name">{{ form.name.label }}</label>

                                {{ form.name }}
                                {% for err in form.name.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--角色设置-->
                            <div class="form-group" id="auth_list">
                            <label for="input_name">{{ form.auths.label }}</label>
                            {{ form.auths }}
                            {% for err in form.auths.errors %}
                                <div class="col-md-12">
                                    <p style="color: red">{{ err }}</p>
                                </div>
                            {% endfor %}
                            </div>
                       </div>
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--3.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-10').addClass('active');
            $('#g-10-1').addClass('active');
        });
    </script>
{% endblock %}

role_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.角色列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 角色管理
                </a>
            </li>
            <li class="active">
                角色列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">角色列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>名称</th>
                                    <th>权限</th>
                                    <th>添加时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.name }}</td>
                                        <td>{{ v.auths }}</td>
                                        <td>{{ v.addtime }}</td>
                                        <td>
                                            <a href="{{url_for('admin.role_edit',id=v.id)}}" class="label label-success">编辑</a>
                                            <a href="{{url_for('admin.role_del',id=v.id)}}" class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.role_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-10').addClass('active');
            $('#g-10-2').addClass('active');
        });
    </script>
{% endblock %}

role_edit.html

<!--1.继承 admin.html-->
{% extends 'admin/admin.html' %}

{% block css %}
    <style>
        #auth_list .col-md-12,#auth_list{
            padding: 0px;
        }
    </style>
{% endblock %}

<!--2.主页面区域-->
{% block content %}
    <!--2.1 页面路径-->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 角色管理
                </a>
            </li>
            <li class="active">
                角色编辑
            </li>
        </ol>
    </section>
    <!--2.2 主内容-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border">
                        <h3 class="box-title">角色编辑</h3>
                    </div>
                    <!--2.2.1 表单-->
                    <form role="form" method="post">
                        <div class="box-body">
                            <!--2.2.2 弹出框-->
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--2.2.3 角色框-->
                            <div class="form-group">
                                <label for="input_name">{{ form.name.label }}</label>
                                {{ form.name(value = role.name) }}
                                {% for err in form.name.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--2.2.4 权限框-->
                            <div class="form-group">
                                <label for="input_name">{{ form.auths.label }}</label>
                                {{ form.auths }}
                                {% for err in form.auths.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                        </div>
                        <!--2.2.4 修改按钮和令牌-->
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>

                    </form>
                </div>
            </div>
        </div>
    </section>


{% endblock %}
<!--3.修改左侧菜单页面内容-->
{% block js %}
    <script>
        $(document).ready(function (){
            $('#g-10').addClass('active');
            $('#g-10-2').addClass('active');
        });
    </script>
{% endblock %}

41.管理员管理

    添加管理员

     41.1 grid.html 添加权限管理

<!--11.管理员管理-->
    <li class="treeview" id="g-11">
        <a href="#">
            <i class="fa fa-home" aria-hidden="true"></i>
            <span>管理员管理</span>
            <span class="label label-primary pull-right">2</span>
        </a>
        <ul class="treeview-menu">
            <li id="g-11-1">
                <a href="{{ url_for('admin.admin_add') }}">
                    <i class="fa fa-circle-o"></i>管理员添加
                </a>
            </li>
        </ul>
        <ul class="treeview-menu">
            <li id="g-11-2">
                <a href="{{url_for('admin.admin_list',page=1)}}">
                    <i class="fa fa-circle-o"></i>管理员列表
                </a>
            </li>
        </ul>
    </li>

    41.2 models.py 编写 Admin模型

# 1.管理员
class Admin(db.Model):
    # 1.设置表格名称(数据库表一致)
    __tablename__ = 'admin'
    # 2.表格是否存在
    __table_args__ = {'useexisting':True}
    # 3.设置映射
    id = db.Column(db.Integer,primary_key=True)# 编号
    name = db.Column(db.String(100),unique=True)# 管理员账号
    pwd = db.Column(db.String(100))# 管理员密码
    is_super = db.Column(db.SmallInteger)# 是否为超级管理员 0为超级管理员
    role_id = db.Column(db.Integer,db.ForeignKey('role.id'))# 所属角色
    addtime = db.Column(db.DateTime,index=True,default=datetime.now())# 添加时间
    '''外键关联'''
    adminlogs = db.relationship('Adminlog',backref='admin') # 管理员登录日志外键关联
    oplogs = db.relationship("Oplog",backref='admin') #管理员操作日志外键关联

    # 4.显示对象属性
    def __repr__(self):
        return '<Admin %r>'%self.name
    # 5.检查密码
    def check_pwd(self,pwd):
        # 系统密码
        print("系统密码:",self.pwd)
        # 用户密码
        print("用户密码:",pwd)
        return check_password_hash(self.pwd,pwd)

    41.3 forms.py 添加  AdminForm表单

# 7.管理员的表单
class AdminForm(FlaskForm):
    name = StringField(
        label='管理员名称',
        validators=[DataRequired("管理员名不能为空")],
        description='管理员名称',
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入管理员名称!!'
        })
    pwd = PasswordField(
        label='管理员密码',
        validators=[DataRequired('管理员密码不能为空')],
        description='管理员密码',
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入管理员密码'
        })
    repwd = PasswordField(
        label='管理员重复密码',
        validators=[DataRequired('管理员重复密码不能为空'),
                    EqualTo('pwd',message='两次密码不一致')],
        description='管理员重复密码',
        render_kw={
            'class': 'form-control',
            'placeholder': '请输入管理员重复密码'
        })
    role_id=SelectField(
        label='所属角色',
        coerce=int,
        choices=[(v.id,v.name) for v in Role.query.all()],
        render_kw={
            'class':'form-control'
        }
    )
    submit = SubmitField(
        '编辑',
        render_kw={
            'class': 'btn btn-primary'
        }
    )

    41.4 views.py添加 admin_add,admin_list,admin_del

admin_add

#33.管理员管理-管理员添加
@admin.route("/admin_add",methods=['GET','POST'])
@admin_login_req
def admin_add():
    form = AdminForm()
    if form.validate_on_submit():
        data=form.data
        admin=Admin(
            name=data['name'],
            pwd=generate_password_hash(data['pwd']),
            role_id=data['role_id'],
            is_super=1
        )
        #33.5
        db.session.add(admin)
        db.session.commit()
        flash("添加管理员成功!",'ok')
    return render_template("admin/admin_add.html",form=form)

,admin_list

#34.管理员管理-管理员列表
@admin.route("/admin_list/<int:page>",methods=['GET'])
def admin_list(page=None):
    #34.1 判断page是否有值
    if page is None:
        page=1
    #34.2分页查询数据
    page_data=Admin.query.join(Role).filter(
        Role.id==Admin.role_id
    ).order_by(
        Admin.addtime.desc()
    ).paginate(page=page,per_page=1)
    '''34.3 根据session中的id值进行查询is_supper的值'''
    #获取登录的用户id的值
    account_id=session['admin_id']
    #查询数据
    adm=Admin.query.filter_by(id=account_id).first_or_404()
    # 将查询数据传递到前端页面

    return render_template("admin/admin_list.html",
                           page_data=page_data,
                           isSuper=adm.is_super)

,admin_del

#35.管理员管理-管理员删除
@admin.route("/admin_del/<int:id>",methods=['GET'])
def admin_del(id=None):
    admin=Admin.query.filter_by(id=id).first_or_404()
    db.session.delete(admin)
    db.session.commit()
    flash("删除管理员成功!",'ok')
    return redirect(url_for("admin.admin_list",page=1))

    41.5 admin文件夹中添加  admin_add.html,admin_list.html

  admin_add.html,

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}

<!--2.设置显示主内容-->
{% block content %}
    <!--内容--->
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 管理员管理
                </a>
            </li>
        </ol>
    </section>
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header with-border" >
                        <h3 class="box-title">添加管理员</h3>
                    </div>
                    <form role="form" method="post" >
                       <div class="box-body">
                            <!--成功弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['ok']) %}
                                <div class="alert alert-success alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-check"></i> 操作成功
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--失败弹出框-->
                            {% for msg in get_flashed_messages(category_filter=['err']) %}
                                <div class="alert alert-danger alert-dismissible">
                                    <button type="button" class="close" data-dismiss="alert"
                                            aria-hidden="true"></button>
                                    <h4>
                                        <i class="icon fa fa-ban"></i> 操作失败
                                    </h4>
                                    {{ msg }}
                                </div>
                            {% endfor %}
                            <!--管理员设置-->
                            <div class="form-group">
                                <label for="input_name">{{ form.name.label }}</label>

                                {{ form.name }}
                                {% for err in form.name.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--3.管理员重复密码-->
                            <div class="form-group">
                                <label for="input_pwd">{{ form.pwd.label }}</label>
                                {{ form.pwd }}
                                {% for err in form.pwd.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--4.管理员重复密码-->
                            <div class="form-group">
                                <label for="input_repwd">{{ form.repwd.label }}</label>
                                {{ form.repwd }}
                                {% for err in form.repwd.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                            <!--5.管理员重复密码-->
                            <div class="form-group">
                                <label for="input_role_id">{{ form.role_id.label }}</label>
                                {{ form.role_id }}
                                {% for err in form.role_id.errors %}
                                    <div class="col-md-12">
                                        <p style="color: red">{{ err }}</p>
                                    </div>
                                {% endfor %}
                            </div>
                       </div>
                        <div class="box-footer">
                            {{ form.csrf_token }}
                            {{ form.submit }}
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--3.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-11').addClass('active');
            $('#g-11-1').addClass('active');
        });
    </script>
{% endblock %}

admin_list.html

<!--1.继承admin.html-->
{% extends 'admin/admin.html' %}
<!--2.导入分页查询页面-->
{% import 'ui/admin_page.html' as pg %}

<!--3.管理员列表主内容-->
{% block content %}
    <section class="content-header">
        <h1>星空电影管理系统 | 后台</h1>
        <ol class="breadcrumb">
            <li>
                <a href="#">
                    <i class="fa fa-dashboard"></i> 管理员管理
                </a>
            </li>
            <li class="active">
                管理员列表
            </li>
        </ol>
    </section>
    <!--查询列表的表单-->
    <section class="content" id="showcontent">
        <div class="row">
            <div class="col-md-12">
                <div class="box box-primary">
                    <div class="box-header">
                        <h3 class="box-title">管理员列表</h3>
                        <div class="box-tools">
                            <div class="input-group input-group-sm"
                                    style="width: 150px">
                                <input type="text" name="table_search"
                                       class="form-control pull-right"
                                       placeholder="请输入关键字">
                                <div class="input-group-btn">
                                    <button type="submit" class="btn btn-default">
                                        <i class="fa fa-search"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!--表格数据显示-->
                    <div class="box-body table-responsive no-padding">
                        <!--成功弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['ok']) %}
                            <div class="alert alert-success alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-check"></i> 操作成功
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--失败弹出框-->
                        {% for msg in get_flashed_messages(category_filter=['err']) %}
                            <div class="alert alert-danger alert-dismissible">
                                <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true"></button>
                                <h4>
                                    <i class="icon fa fa-ban"></i> 操作失败
                                </h4>
                                {{ msg }}
                            </div>
                        {% endfor %}
                        <!--表格显示-->
                        <table class="table table-hover">
                            <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>管理员名称</th>
                                    <th>管理员类型</th>
                                    <th>管理员角色</th>
                                    <th>添加时间</th>
                                    {% if isSuper==0 %}
                                        <th>操作事项</th>
                                    {% endif %}
                                </tr>
                                {% for v in page_data.items %}
                                    <tr>
                                        <td>{{ v.id }}</td>
                                        <td>{{ v.name }}</td>
                                        <td>
                                            {% if v.is_super==0 %}
                                            超级管理员
                                            {% else %}
                                            普通管理员
                                            {% endif %}
                                        </td>
                                        <td>{{ v.role.name }}</td>
                                        <td>{{ v.addtime }}</td>
                                        {% if isSuper==0 %}
                                            <td>
                                               <a href="{{url_for('admin.admin_del',id=v.id)}}" class="label label-danger">删除</a>
                                            </td>
                                        {% endif %}
                                    </tr>
                                {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
                <!--分页显示-->
                <div class="box-footer clearfix">
                    {{ pg.page(page_data,'admin.admin_list') }}
                </div>
            </div>
        </div>
    </section>
{% endblock %}

<!--4.js区域-->
{% block js %}
    <script>
        $(documen).ready(function (){
            $('#g-11').addClass('active');
            $('#g-11-2').addClass('active');
        });
    </script>
{% endblock %}

42.修改密码

42.1 admin.html 添加修改密码请求

42.2 views.py中 添加pwd函数

42.3admin文件夹中添加pwd.html页面

43.退出系统

43.1 admin.html 添加退出系统请求

43.2 views.py中 添加logout函数

44.登录验证器

44.1 views.py中添加admin_login_req(f)

44.2 将所有的请求上方添加登录装饰器

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值