精华内容
下载资源
问答
  • flash("标签添加成功!", 'info') return redirect(url_for('admin.tag_add')) return render_template('admin/tag_add.html', form=form) 修改前端代码 {% for message in get_flashed_messages(category...

    后台管理

    实现后台管理系统使用flask sqlalchemy结合mysql数据库进行增删改查操作、分页的使用、路由装饰器定义、模板中变量调用、登录会话机制、上传文件、flask wtforms表单使用。

    管理员登录

    models进行重构,将数据库的配置信息放在app/__init__.py文件中

    from flask_sqlalchemy import SQLAlchemy
    
    
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqlconnector://root:123456@127.0.0.1:3306/movie'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    app.config['SECRET_KEY'] = 'cb34xxxxxxxxxxxxxxxxxxbae30d90f6'
    
    db = SQLAlchemy(app)

    models文件中直接引入db

    from app import db

    定义登陆表单字段
    app/admin/forms.py

    from flask_wtf import FlaskForm
    from wtforms import StringField, PasswordField, SubmitField
    from wtforms.validators import DataRequired, ValidationError
    
    from app.models import Admin
    
    
    class LoginForm(FlaskForm):
        '''
        管理员登陆表单
        '''
        account = StringField(
            label='账号',
            validators=[
                DataRequired("请输入账号!")
            ],
            description="账号",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入账号!",
                "required": "required"
            }
        )
        pwd = PasswordField(
            label='密码',
            validators=[
                DataRequired("请输入密码!")
            ],
            description="密码",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入密码!",
                "required": "required"
            }
        )
        submit = SubmitField(
            '登录',
            render_kw={
                "class": "btn btn-primary btn-block btn-flat",
            }
        )
    
        def validate_account(self, field):
            account = field.data
            admin = Admin.query.filter_by(name=account).count()
            if admin == 0:
                raise ValidationError("账号不存在!")

    render_kw里的样式是前端代码中的

    编写试图函数

    # 装饰器用来进行访问控制
    def admin_login_req(func):
        @wraps(func)
        def decorated_function(*args, **kwargs):
            if session.get('admin', None) is None:
                return redirect(url_for('admin.login', next=request.url))
            return func(*args, **kwargs)
        return decorated_function
    @admin.route('/login/', methods=['GET', 'POST'])
    def login():
        form = LoginForm()
        if form.validate_on_submit():
            data = form.data
            admin = Admin.query.filter_by(name=data['account']).first()
            if not admin.check_pwd(data['pwd']):
                flash("账号或密码错误! ")
                return redirect(url_for('admin.login'))
            session['admin'] = data['account']
            return redirect((request.args.get('next') or url_for('admin.index')))
        return render_template('admin/login.html', form=form)
    
    
    @admin.route('/logout/')
    @admin_login_req
    def logout():
        session.clear()
        return redirect(url_for('admin.login'))

    在每一个需要进行登陆才能操作的视图函数中加入装饰器,像logout视图一样
    Admin模型中添加密码校验函数

        def check_pwd(self, pwd):
            from werkzeug.security import check_password_hash
            return check_password_hash(self.pwd, pwd)

    修改模板app/templates/admin/login.html

        <div class="login-box-body">
            {% for message in get_flashed_messages() %}
                <p class="login-box-msg" style="color: red">{{ message }}</p>
            {% endfor %}
    
            <form action="" method="post" id="form-data">
                <div class="form-group has-feedback">
                    {{ form.account }}
                    <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
                    {% for err in form.account.errors %}
                        <div class="col-md-12" id="input_user" style="color: red">{{ err }}</div>
                    {% endfor %}
    
                </div>
                <div class="form-group has-feedback">
                    {{ form.pwd }}
                    <span class="glyphicon glyphicon-lock form-control-feedback"></span>
                    {% for err in form.pwd.errors %}
                        <div class="col-md-12" id="input_pwd" style="color: red">{{ err }}</div>
                    {% endfor %}
                </div>
                <div class="row">
                    <div class="col-xs-8">
                    </div>
                    <div class="col-xs-4">
                        {{ form.submit }}
                        {{ form.csrf_token }}
                    </div>
                </div>
            </form>
        </div>

    标签管理

    创建一个表单form
    app/admin/forms.py

    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"
            }
        )
    添加标签

    视图函数

    @admin.route('/tag/add/', methods=['GET', 'POST'])
    @admin_login_req
    def tag_add():
        form = TagForm()
        if form.validate_on_submit():
            data = form.data
            tag = Tag.query.filter_by(name=data['name']).count()
            if tag == 1:
                flash("标签已存在!", 'error')
                return redirect(url_for('admin.tag_add'))
            tag = Tag(
                name=data['name']
            )
            db.session.add(tag)
            db.session.commit()
            flash("标签添加成功!", 'info')
            return redirect(url_for('admin.tag_add'))
        return render_template('admin/tag_add.html', form=form)

    修改前端代码

    <form role="form" method="post">
        <div class="box-body">
            {% for message in get_flashed_messages(category_filter=['info']) %}
                <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>
                    {{ message }}
                </div>
            {% endfor %}
            {% for message in get_flashed_messages(category_filter=['error']) %}
                <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>
                    {{ message }}
                </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" id="input_user" style="color: red">{{ err }}</div>
                {% endfor %}
            </div>
        </div>
        <div class="box-footer">
            {{ form.submit }}
            {{ form.csrf_token }}
        </div>
    </form>
    标签列表

    视图函数

    @admin.route('/tag/list/<int:page>/')
    @admin_login_req
    def tag_list(page=1):
        if page <= 0:
            page = 1
        page_data = Tag.query.order_by(
            Tag.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/tag_list.html', page_data=page_data)

    修改前端代码

    <div class="box-body table-responsive no-padding">
        {% for message in get_flashed_messages(category_filter=['info']) %}
            <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>
                {{ message }}
            </div>
        {% endfor %}
        <table class="table table-hover">
            <tbody>
            <tr>
                <th>编号</th>
                <th>名称</th>
                <th>添加时间</th>
                <th>操作事项</th>
            </tr>
            {% for tag in page_data.items %}
                <tr>
                    <td>{{ tag.id }}</td>
                    <td>{{ tag.name }}</td>
                    <td>{{ tag.addtime }}</td>
                    <td>
                        <a href="{{ url_for('admin.tag_edit', id=tag.id) }}" class="label label-success">编辑</a>
                        &nbsp;
                        <a href="{{ url_for('admin.tag_del', id=tag.id) }}" class="label label-danger">删除</a>
                    </td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
    </div>

    当标签较多时,需要对标签进行分页
    分页http://www.pythondoc.com/flask-sqlalchemy/api.html?highlight=paginate#id4

    新建一个分页的macro
    app/templates/ui/admin_page.html

    {% macro pagination(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 == data.page %}
                        <li class="active"><a href="#">{{ v }}</a></li>
                    {% else %}
                        <li><a href="{{ url_for(url, page=v) }}">{{ v }}</a></li>
                    {% 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 %}

    在标签列表中使用这个macro

    {% extends 'admin/admin.html' %}
    {% from 'ui/admin_page.html' import pagination %}
    
    ...
    
    <div class="box-footer clearfix">
        {{ pagination(page_data, 'admin.tag_list') }}
    </div>
    删除标签

    视图函数

    @admin.route('/tag/del/<int:id>/')
    @admin_login_req
    def tag_del(id=None):
        tag = Tag.query.filter_by(id=id).first_or_404()
        db.session.delete(tag)
        db.session.commit()
        flash('删除标签成功!', 'info')
        return redirect(url_for('admin.tag_list', page=1))

    修改标签列表中删除按钮的a标签

    <a href="{{ url_for('admin.tag_del', id=tag.id) }}" class="label label-danger">删除</a>
    修改标签

    视图函数

    @admin.route('/tag/edit/<int:id>/', methods=['GET', 'POST'])
    @admin_login_req
    def tag_edit(id=None):
        form = TagForm()
        tag = Tag.query.get_or_404(id)
        if form.validate_on_submit():
            data = form.data
            tag_count = Tag.query.filter_by(name=data['name']).count()
            if tag.name != data['name'] and tag_count == 1:
                flash("标签已存在!", 'error')
                return redirect(url_for('admin.tag_edit', id=id))
            tag.name=data['name']
            db.session.add(tag)
            db.session.commit()
            flash("标签修改成功!", 'info')
            return redirect(url_for('admin.tag_list', page=1))
        return render_template('admin/tag_edit.html', form=form, tag=tag)

    新建app/templates/admin/tag_edit.html,用来进行标签的修改
    代码和添加标签中的几乎一致,只是需要显示标签的名字

    <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" id="input_user" style="color: red">{{ err }}</div>
        {% endfor %}
    </div>

    电影管理

    新建电影表单
    app/admin/forms.py

    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",
                "id": "input_info",
            }
        )
    
        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,
            choices=[(v.id, v.name) for v in tags],
            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",
                "id": "input_release_time",
                "placeholder": "请选择上映时间!"
            }
        )
        submit = SubmitField(
            '编辑',
            render_kw={
                "class": "btn btn-primary"
            }
        )
    
        def validate_title(self, field):
            title = field.data
            num = Movie.query.filter_by(title=title).count()
            if num > 0:
                raise ValidationError("该电影已存在!")

    在app初始化文件中定义上传文件的目录

    app.config['UP_DIR'] = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'static/uploads/')
    添加电影

    视图函数
    文件名称检测

    from werkzeug.utils import secure_filename
    
    def change_filename(filename):
        fileinfo = os.path.splitext(filename)
        filename = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + str(uuid.uuid4().hex) + fileinfo[-1]
        return filename
    @admin.route('/movie/add/', methods=['GET', 'POST'])
    @admin_login_req
    def movie_add():
        form = MovieForm()
        if form.validate_on_submit():
            data = form.data
            file_url = secure_filename(form.url.data.filename)
            file_logo = secure_filename(form.logo.data.filename)
    
            if not os.path.exists(app.config['UP_DIR']):
                os.makedirs(app.config['UP_DIR'])
                os.chmod(app.config['UP_DIR'], 6)
    
            url = change_filename(file_url)
            logo = change_filename(file_logo)
            form.url.data.save(app.config['UP_DIR'] + url)
            form.logo.data.save(app.config['UP_DIR'] + logo)
    
            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']
            )
            db.session.add(movie)
            db.session.commit()
            flash('电影添加成功!', 'info')
            return redirect(url_for('admin.movie_add'))
        return render_template('admin/movie_add.html', form=form)

    app/templates/admin/movie_add.html

    {% extends 'admin/admin.html' %}
    
    {% 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>
                        <form role="form" method="post" enctype="multipart/form-data">
                            <div class="box-body">
                                {% for message in get_flashed_messages(category_filter=['info']) %}
                                    <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>
                                        {{ message }}
                                    </div>
                                {% endfor %}
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                    <div style="margin-top:5px;">
    {#                                    <div id="moviecontainer"></div>#}
                                    </div>
                                </div>
                                <div class="form-group">
                                    <label for="input_info">{{ form.info.label }}</label>
                                    {{ form.info }}
                                    {% for err in form.info.errors %}
                                        <div class="col-md-12" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
    {#                                <img data-src="holder.js/262x166" style="margin-top:5px;" class="img-responsive"#}
    {#                                     alt="">#}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <div class="form-group">
                                    <label for="input_area">{{ form.area.label }}</label>
                                    {{ form.area }}
                                    {% for err in form.area.errors %}
                                        <div class="col-md-12" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <div class="form-group">
                                    <label for="input_length">{{ form.length.label }}</label>
                                    {{ form.length }}
                                    {% for err in form.length.errors %}
                                        <div class="col-md-12" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <div class="form-group">
                                    <label for="input_release_time">{{ form.release_time.label }}</label>
                                    {{ form.release_time }}
                                    {% for err in form.release_time.errors %}
                                        <div class="col-md-12" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                            </div>
                            <div class="box-footer">
                                {{ form.csrf_token }}
                                {{ form.submit }}
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </section>
    {% endblock %}
    电影列表

    视图函数

    @admin.route('/movie/list/<int:page>/')
    @admin_login_req
    def movie_list(page=1):
        if page <= 0:
            page = 1
        page_data = Movie.query.join(Tag).filter(
            Tag.id == Movie.tag_id
        ).order_by(
            Movie.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/movie_list.html', page_data=page_data)

    app/templates/admin/movie_list.html

    {% extends 'admin/admin.html' %}
    {% from 'ui/admin_page.html' import pagination %}
    {% 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 message in get_flashed_messages(category_filter=['info']) %}
                                <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>
                                    {{ message }}
                                </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 data in page_data.items %}
    
                                    <tr>
                                        <td>{{ data.id }}</td>
                                        <td>{{ data.title }}</td>
                                        <td>{{ data.length }}分钟</td>
                                        <td>{{ data.tag.name }}</td>
                                        <td>{{ data.area }}</td>
                                        <td>{{ data.star }}</td>
                                        <td>{{ data.playnum }}</td>
                                        <td>{{ data.commentnum }}</td>
                                        <td>{{ data.release_time }}</td>
                                        <td>
                                            <a href="{{ url_for('admin.movie_edit', id=data.id) }}" class="label label-success">编辑</a>
                                            &nbsp;
                                            <a href="{{ url_for('admin.movie_del', id=data.id) }}"
                                               class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
    
                                </tbody>
                            </table>
                        </div>
                        <div class="box-footer clearfix">
                            {{ pagination(page_data, 'admin.movie_list') }}
                        </div>
                    </div>
                </div>
            </div>
        </section>
    {% endblock %}
    
    {% block js %}
        <script>
            $(document).ready(function () {
                $('#g-3').addClass('active');
                $('#g-3-2').addClass('active');
            })
        </script>
    {% endblock %}

    修改app/templates/admin/grid.html

    <li id="g-3-2">
        <a href="{{ url_for('admin.movie_list', page=1) }}">
            <i class="fa fa-circle-o"></i> 电影列表
        </a>
    </li>
    删除电影

    视图函数

    @admin.route('/movie/del/<int:id>/')
    @admin_login_req
    def movie_del(id=None):
        movie = Movie.query.get_or_404(int(id))
        db.session.delete(movie)
        db.session.commit()
        flash('电影删除成功!', 'info')
        return redirect(url_for('admin.movie_list', page=1))

    修改一下前端删除按钮a标签

    修改电影

    视图函数

    @admin.route('/movie/edit/<int:id>', methods=['GET', 'POST'])
    @admin_login_req
    def movie_edit(id=None):
        form = MovieForm()
    
        # # 如果不设置,默认依然会让上传文件
        # form.url.flags.required = False
        # form.logo.flags.required = False
    
        # # 取消校验,可能没有上传文件
        # form.url.validators=[]
        # form.logo.validators=[]
        # 取消后如果没有上传文件,form.url.data是一个str对象
        # 上传文件后是才是一个文件对象
        # 为了方便,设置必须上传文件
    
        movie=Movie.query.get_or_404(int(id))
        if  request.method =='GET':
            form.info.data = movie.info
            form.tag_id.data = movie.tag_id
            form.star.data = movie.star
        if form.validate_on_submit():
            data = form.data
            movie_count = Movie.query.filter_by(title=data['title']).count()
            if movie_count == 1 and movie.title != data['title']:
                flash('该电影已存在!', 'error')
                return redirect(url_for('admin.movie_edit', id=id))
    
            if not os.path.exists(app.config['UP_DIR']):
                os.makedirs(app.config['UP_DIR'])
                os.chmod(app.config['UP_DIR'], 6)
    
            if form.url.data.filename !='':
                file_url = secure_filename(form.url.data.filename)
                movie.url = change_filename(file_url)
                form.url.data.save(app.config['UP_DIR'] + movie.url)
    
            if form.logo.data.filename != '':
                file_logo = secure_filename(form.logo.data.filename)
                movie.logo = change_filename(file_logo)
                form.logo.data.save(app.config['UP_DIR'] + movie.logo)
    
            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']
    
            db.session.add(movie)
            db.session.commit()
            flash('电影修改成功!', 'info')
            return redirect(url_for('admin.movie_add', id=movie.id))
        return render_template('admin/movie_edit.html', form=form, movie=movie)

    app/templates/admin/movie_edit.html

    {% extends 'admin/admin.html' %}
    
    {% 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>
                        <form role="form" method="post" enctype="multipart/form-data">
                            <div class="box-body">
                                {% for message in get_flashed_messages(category_filter=['info']) %}
                                    <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>
                                        {{ message }}
                                    </div>
                                {% endfor %}
                                {% for message in get_flashed_messages(category_filter=['error']) %}
                                    <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>
                                        {{ message }}
                                    </div>
                                {% endfor %}
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                    <div style="margin-top:5px;">
                                        <div id="moviecontainer"></div>
                                    </div>
                                </div>
                                <div class="form-group">
                                    <label for="input_info">{{ form.info.label }}</label>
                                    {{ form.info }}
                                    {% for err in form.info.errors %}
                                        <div class="col-md-12" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                    <img src="{{ url_for('static', filename='uploads/'+movie.logo) }}" style="margin-top:5px;" class="img-responsive"
                                         alt="">
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                            </div>
                            <div class="box-footer">
                                {{ form.csrf_token }}
                                {{ form.submit }}
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </section>
    {% endblock %}
    
    {% block js %}
        <script src="{{ url_for('static',filename='jwplayer/jwplayer.js') }}"></script>
        <script type="text/javascript">
            jwplayer.key = "P9VTqT/X6TSP4gi/hy1wy23BivBhjdzVjMeOaQ==";
    
        </script>
        <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: "download"
                }],
                skin: {
                    name: "vapor"
                },
                "playlist.position": "left",
                "playlist.size": 200,
                height: 250,
                width: 387,
            });
    
        </script>
        <script>
            $(document).ready(function () {
                $('#input_release_time').datepicker({
                    autoclose: true,
                    format: 'yyyy-mm-dd',
                    language: 'zh-CN',
                });
            });
    
        </script>
        <script>
            $(document).ready(function () {
                $('#g-3').addClass('active');
                $('#g-3-1').addClass('active');
            })
        </script>
    {% endblock %}

    修改电影列表中的编辑按钮

    <a href="{{ url_for('admin.movie_edit', id=data.id) }}" class="label label-success">编辑</a>

    预告管理

    创建预告表单

    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"
            }
        )
    
        def validate_title(self, field):
            title = field.data
            num = Preview.query.filter_by(title=title).count()
            if num > 0:
                raise ValidationError("该预告已存在!")
    添加预告

    视图函数

    @admin.route('/preview/add/', methods=['GET', 'POST'])
    @admin_login_req
    def preview_add():
        form = PreviewForm()
        if form.validate_on_submit():
            data = form.data
            file_logo = secure_filename(form.logo.data.filename)
    
            if not os.path.exists(app.config['UP_DIR']):
                os.makedirs(app.config['UP_DIR'])
                os.chmod(app.config['UP_DIR'], 6)
    
            logo = change_filename(file_logo)
            form.logo.data.save(app.config['UP_DIR']+logo)
            preview = Preview(
                title=data['title'],
                logo=logo
            )
            db.session.add(preview)
            db.session.commit()
            flash("预告添加成功!", 'info')
            return redirect(url_for('admin.preview_add'))
        return render_template('admin/preview_add.html', form = form)

    app/templates/admin/preview_add.html

    {% extends 'admin/admin.html' %}
    
    {% 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>
                        <form role="form" method="post" enctype="multipart/form-data">
                            <div class="box-body">
                                {% for message in get_flashed_messages(category_filter=['info']) %}
                                    <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>
                                        {{ message }}
                                    </div>
                                {% endfor %}
                                {% for message in get_flashed_messages(category_filter=['error']) %}
                                    <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>
                                        {{ message }}
                                    </div>
                                {% endfor %}
                                <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" id="input_user" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                </div>
                                <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" id="input_user" style="color: red">{{ err }}</div>
                                    {% endfor %}
                                    <img data-src="holder.js/700x320" 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 %}
    
    {% block js %}
        <script>
            $(document).ready(function () {
                $('#g-4').addClass('active');
                $('#g-4-1').addClass('active');
            })
        </script>
    {% endblock %}
    预告列表

    视图函数

    @admin.route('/preview/list/<int:page>/')
    @admin_login_req
    def preview_list(page=1):
        if page <= 0:
            page = 1
        page_data = Preview.query.order_by(
            Preview.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/preview_list.html', page_data=page_data)

    app/templates/admin/preview_list.html

    {% extends 'admin/admin.html' %}
    {% from 'ui/admin_page.html' import pagination %}
    {% 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 message in get_flashed_messages(category_filter=['info']) %}
                                <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>
                                    {{ message }}
                                </div>
                            {% endfor %}
                            <table class="table table-hover">
                                <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>预告标题</th>
                                    <th>预告封面</th>
                                    <th>添加时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for data in page_data.items %}
                                    <tr>
                                        <td>{{ data.id }}</td>
                                        <td>{{ data.title }}</td>
                                        <td>
                                            <img src="{{ url_for('static', filename='uploads/'+data.logo) }}"
                                                 class="img-responsive center-block" alt="" style="width: 140px">
                                        </td>
                                        <td>{{ data.addtime }}</td>
                                        <td>
                                            <a href="{{ url_for('admin.preview_edit', id=data.id) }}" class="label label-success">编辑</a>
                                            &nbsp;
                                            <a href="{{ url_for('admin.preview_del', id=data.id) }}"
                                               class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                                </tbody>
                            </table>
                        </div>
                        <div class="box-footer clearfix">
                            {{ pagination(page_data, 'admin.preview_list') }}
                        </div>
                    </div>
                </div>
            </div>
        </section>
    {% endblock %}
    
    {% block js %}
        <script>
            $(document).ready(function () {
                $('#g-4').addClass('active');
                $('#g-4-2').addClass('active');
            })
        </script>
    {% endblock %}

    修改app/templates/admin/grid.html

    <li id="g-4-2">
        <a href="{{ url_for('admin.preview_list', page=1) }}">
            <i class="fa fa-circle-o"></i> 预告列表
        </a>
    </li>
    删除预告

    视图函数

    @admin.route('/preview/del/<int:id>/')
    @admin_login_req
    def preview_del(id=None):
        preview = Preview.query.get_or_404(int(id))
        db.session.delete(preview)
        db.session.commit()
        flash('预告删除成功!', 'info')
        return redirect(url_for('admin.preview_list', page=1))
    修改预告

    视图函数

    @admin.route('/preview/edit/<int:id>/', methods=['GET', 'POST'])
    @admin_login_req
    def preview_edit(id=None):
        form = PreviewForm()
        preview = Preview.query.get_or_404(int(id))
    
        if request.method == 'GET':
            form.title.data = preview.title
        if form.validate_on_submit():
            data = form.data
    
            if not os.path.exists(app.config['UP_DIR']):
                os.makedirs(app.config['UP_DIR'])
                os.chmod(app.config['UP_DIR'], 6)
    
            if form.logo.data.filename != '':
                file_logo = secure_filename(form.logo.data.filename)
                preview.logo = change_filename(file_logo)
                form.logo.data.save(app.config['UP_DIR'] + preview.logo)
    
            preview.title=data['title']
            db.session.add(preview)
            db.session.commit()
    
            flash('预告修改成功!', 'info')
            return redirect(url_for('admin.preview_edit', id=id))
        return render_template('admin/preview_edit.html', form=form, preview=preview)

    app/templates/admin/preview_edit.html,代码拷贝添加预告,修改部分

    <div class="form-group">
        <label for="input_title">{{ form.title.label }}</label>
        {{ form.title(value=preview.title) }}
        {% for err in form.title.errors %}
            <div class="col-md-12" id="input_user" style="color: red">{{ err }}</div>
        {% endfor %}
    </div>
    <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" id="input_user" style="color: red">{{ err }}</div>
        {% endfor %}
        <img src="{{ url_for('static', filename='uploads/'+preview.logo) }}" style="margin-top:5px;" class="img-responsive"
             alt="">
    </div>

    会员管理

    会员列表
    @admin.route('/user/list/<int:page>/')
    @admin_login_req
    def user_list(page=1):
        if page <= 0:
            page = 1
        page_data = User.query.order_by(
            User.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/user_list.html', page_data=page_data)

    app/templates/admin/user_list.html

    {% extends 'admin/admin.html' %}
    {% from 'ui/admin_page.html' import pagination %}
    
    {% 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 message in get_flashed_messages(category_filter=['info']) %}
                                <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>
                                    {{ message }}
                                </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>
                                </tr>
                                {% for data in page_data.items %}
    
    
    
                                    <tr>
                                        <td>{{ data.id }}</td>
                                        <td>{{ data.name }}</td>
                                        <td>{{ data.email }}</td>
                                        <td>{{ data.phone }}</td>
                                        <td>
                                            <img src="{{ url_for('static', filename='uploads/users/'+data.face) }}"
                                                 style="width: 50px" class="img-responsive center-block" alt="">
                                        </td>
                                        {#                                    <td>正常/冻结</td>#}
                                        <td>{{ data.addtime }}</td>
                                        <td>
                                            <a class="label label-success"
                                               href="{{ url_for('admin.user_view', id=data.id) }}">查看</a>
                                            {#                                        &nbsp;#}
                                            {#                                        <a class="label label-info">解冻</a>#}
                                            {#                                        &nbsp;#}
                                            {#                                        <a class="label label-warning">冻结</a>#}
                                            &nbsp;
                                            <a href="{{ url_for('admin.user_del', id=data.id) }}"
                                               class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                                </tbody>
                            </table>
                        </div>
                        <div class="box-footer clearfix">
                            {{ pagination(page_data, 'admin.preview_list') }}
                        </div>
                    </div>
                </div>
            </div>
        </section>
    {% endblock %}
    
    {% block js %}
        <script>
            $(document).ready(function () {
                $('#g-5').addClass('active');
                $('#g-5-1').addClass('active');
            })
        </script>
    {% endblock %}
    查看会员
    @admin.route('/user/view/<int:id>/')
    @admin_login_req
    def user_view(id=None):
        user = User.query.get_or_404(int(id))
        return render_template('admin/user_view.html', user=user)
    <table class="table table-hover">
        <tbody>
        <tr>
            <td class="td_bd">编号:</td>
            <td>1</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>
                <img src="{{ url_for('static', filename='uploads/users/'+user.face) }}" style="width: 100px" class="img-responsive" alt="">
            </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>
    删除用户
    @admin.route('/user/del/<int:id>/')
    @admin_login_req
    def user_del(id=None):
        user = User.query.get_or_404(int(id))
        db.session.delete(user)
        db.session.commit()
        flash('会员删除成功!', 'info')
        return redirect(url_for('admin.user_list', page=1))

    评论管理

    评论列表
    @admin.route('/comment/list/<int:page>/')
    @admin_login_req
    def comment_list(page=1):
        if page <= 0:
            page = 1
        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=10)
        return render_template('admin/comment_list.html', page_data=page_data)
    <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 message in get_flashed_messages(category_filter=['info']) %}
                                <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>
                                    {{ message }}
                                </div>
                            {% endfor %}
                            {% for data in page_data.items %}
    
    
    
                                <div class="box-comment">
                                    <img class="img-circle img-sm"
                                         src="{{ url_for('static',filename='uploads/users/'+data.user.face) }}"
                                         alt="User Image">
                                    <div class="comment-text">
                                        <span class="username">
                                            {{ data.user.name }}
                                            <span class="text-muted pull-right">
                                                <i class="fa fa-calendar" aria-hidden="true"></i>
                                                &nbsp;
                                                {{ data.addtime }}
                                            </span>
                                        </span>
                                        关于电影<a>《{{ data.movie.title }}》</a>的评论:{{ data.content }}
                                        <br><a href="{{ url_for('admin.comment_del', id=data.id) }}"
                                               class="label label-danger pull-right">删除</a>
                                    </div>
                                </div>
                            {% endfor %}
                        </div>
                        <div class="box-footer clearfix">
                            {{ pagination(page_data, 'admin.preview_list') }}
                        </div>
                    </div>
                </div>
            </div>
        </section>
    删除评论
    @admin.route('/comment/del/<int:id>/')
    @admin_login_req
    def comment_del(id=None):
        comment = Comment.query.get_or_404(int(id))
        db.session.delete(comment)
        db.session.commit()
        flash('评论删除成功!', 'info')
        return redirect(url_for('admin.comment_list', page=1))

    收藏管理

    收藏列表
    @admin.route('/moviecol/list/<int:page>/')
    @admin_login_req
    def moviecol_list(page=1):
        if page <= 0:
            page = 1
        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=10)
        return render_template('admin/moviecol_list.html', page_data=page_data)
    <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 message in get_flashed_messages(category_filter=['info']) %}
                                <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>
                                    {{ message }}
                                </div>
                            {% endfor %}
                            <table class="table table-hover">
                                <tbody>
                                <tr>
                                    <th>编号</th>
                                    <th>电影</th>
                                    <th>用户</th>
                                    <th>添加时间</th>
                                    <th>操作事项</th>
                                </tr>
                                {% for data in page_data.items %}
                                    <tr>
                                        <td>{{ data.id }}</td>
                                        <td>{{ data.movie.title }}</td>
                                        <td>{{ data.user.name }}</td>
                                        <td>{{ data.addtime }}</td>
                                        <td>
                                            {#                                    <a class="label label-success">编辑</a>#}&nbsp;
                                            <a href="{{ url_for('admin.moviecol_del', id=data.id) }}"
                                               class="label label-danger">删除</a>
                                        </td>
                                    </tr>
                                {% endfor %}
                                </tbody>
                            </table>
                        </div>
                        <div class="box-footer clearfix">
                            {{ pagination(page_data, 'admin.moviecol_list') }}
                        </div>
                    </div>
                </div>
            </div>
        </section>
    删除收藏
    @admin.route('/moviecol/del/<int:id>/')
    @admin_login_req
    def moviecol_del(id=None):
        moviecol = Moviecol.query.get_or_404(int(id))
        db.session.delete(moviecol)
        db.session.commit()
        flash('收藏删除成功!', 'info')
        return redirect(url_for('admin.moviecol_list', page=1))

    修改密码

    新建一个form表单

    class PwdForm(FlaskForm):
        old_pwd = PasswordField(
            label='旧密码',
            validators=[
                DataRequired("请输入旧密码!"),
            ],
            description='旧密码',
            render_kw={
                "class": "form-control",
                "placeholder": "请输入旧密码!"
            }
        )
    
        new_pwd = PasswordField(
            label='新密码',
            validators=[
                DataRequired("请输入新密码!"),
            ],
            description='新密码',
            render_kw={
                "class": "form-control",
                "placeholder": "请输入新密码!"
            }
        )
        submit = SubmitField(
            '编辑',
            render_kw={
                "class": "btn btn-primary",
            }
        )
    
        def validate_old_pwd(self, field):
            from flask import session
            pwd = field.data
            name = session['admin']
            admin = Admin.query.filter_by(name=name).first()
            if not admin.check_pwd(pwd):
                raise ValidationError("密码输入错误!")
    @admin.route('/pwd/', methods=['GET', 'POST'])
    @admin_login_req
    def pwd():
        form = PwdForm()
        if form.validate_on_submit():
            data = form.data
            admin = Admin.query.filter_by(name=session['admin']).first()
    
            from werkzeug.security import generate_password_hash
            admin.pwd = generate_password_hash(data['new_pwd'])
    
            db.session.add(admin)
            db.session.commit()
    
            flash("密码修改成功,请重新登录!", 'info')
            return redirect(url_for('admin.logout'))
        return render_template('admin/pwd.html', form=form)

    将信息展示出来login.html

            {% for message in get_flashed_messages(category_filter=['info']) %}
                <p class="login-box-msg" style="color: green">{{ message }}</p>
            {% endfor %}
            {% for message in get_flashed_messages(category_filter=['error']) %}
                <p class="login-box-msg" style="color: red">{{ message }}</p>
            {% endfor %}

    运行发现并没有显示密码修改成功,请重新登录!这条提示
    是因为flash是基于session的,前面退出的视图函数中我们清除了所有的session

    日志管理

    @admin.route('/oplog/list/<int:page>/')
    @admin_login_req
    def oplog_list(page=1):
        if page <= 0:
            page = 1
        page_data = Oplog.query.join(
            Admin
        ).filter(
            Admin.id==Oplog.admin_id,
        ).order_by(
            Oplog.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/oplog_list.html', page_data=page_data)
    
    
    @admin.route('/adminloginlog/list/<int:page>/')
    @admin_login_req
    def adminloginlog_list(page=1):
        if page <= 0:
            page = 1
        page_data = Adminlog.query.join(
            Admin
        ).filter(
            Admin.id==Adminlog.admin_id,
        ).order_by(
            Adminlog.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/adminloginlog_list.html', page_data=page_data)
    
    
    @admin.route('/userloginlog/list/<int:page>/')
    @admin_login_req
    def userloginlog_list(page=1):
        if page <= 0:
            page = 1
        page_data = Userlog.query.join(
            User
        ).filter(
            User.id==Userlog.user_id,
        ).order_by(
            Userlog.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/userloginlog_list.html',page_data=page_data)

    修改对应的前端文件
    在其它视图函数中添加对应到操作日志,例如添加标签

            flash("标签添加成功!", 'info')
    
            oplog = Oplog(
                admin_id=session['admin_id'],
                ip=request.remote_addr,
                reason='添加标签< {} >'.format(data['name'])
            )
    
            db.session.add(oplog)
            db.session.commit()
            return redirect(url_for('admin.tag_add'))

    基于角色的访问控制

    权限管理

    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",
            }
        )
    添加权限
    @admin.route('/auth/add/', methods=['GET', 'POST'])
    @admin_login_req
    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('权限添加成功!', 'info')
        return render_template('admin/auth_add.html',form=form)
    权限列表
    @admin.route('/auth/list/<int:page>/')
    @admin_login_req
    def auth_list(page=1):
        if page <= 0:
            page = 1
        page_data = Auth.query.order_by(
            Auth.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/auth_list.html',page_data=page_data)
    删除权限
    @admin.route('/auth/del/<int:id>/')
    @admin_login_req
    def auth_del(id=None):
        auth = Auth.query.get_or_404(int(id))
        db.session.delete(auth)
        db.session.commit()
        flash('权限删除成功!', 'info')
        return redirect(url_for('admin.auth_list', page=1))
    编辑权限
    @admin.route('/auth/edit/<int:id>/', methods=['GET', 'POST'])
    @admin_login_req
    def auth_edit(id=None):
        form = AuthForm()
        auth = Auth.query.get_or_404(int(id))
    
        if form.validate_on_submit():
            data = form.data
            auth.name =data['name']
            auth.url=data['url']
    
            db.session.add(auth)
            db.session.commit()
    
            flash('权限修改成功!', 'info')
            return redirect(url_for('admin.auth_edit', id=id))
        return render_template('admin/auth_edit.html',form=form, auth=auth)

    修改对应的前端文件

    角色管理

    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 auths],
            description='权限列表',
            render_kw={
                "class": "form-control",
            }
        )
        submit = SubmitField(
            '编辑',
            render_kw={
                "class": "btn btn-primary",
            }
        )
    添加角色
    @admin.route('/role/add/', methods=['GET', 'POST'])
    @admin_login_req
    def role_add():
        form = RoleForm()
        if form.validate_on_submit():
            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('角色添加成功!', 'info')
        return render_template('admin/role_add.html',form=form)
    角色列表
    @admin.route('/role/list/<int:page>/')
    @admin_login_req
    def role_list(page=1):
        if page <= 0:
            page = 1
        page_data = Role.query.order_by(
            Role.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/role_list.html',page_data=page_data)
    删除角色
    @admin.route('/role/del/<int:id>/')
    @admin_login_req
    def role_del(id=None):
        role = Role.query.get_or_404(int(id))
        db.session.delete(role)
        db.session.commit()
        flash('角色删除成功!', 'info')
        return redirect(url_for('admin.role_list', page=1))
    修改权限
    @admin.route('/role/edit/<int:id>/', methods=['GET', 'POST'])
    @admin_login_req
    def role_edit(id=None):
        form = RoleForm()
        role = Role.query.get_or_404(int(id))
    
        if request.method == 'GET':
            auths = role.auths
            form.auths.data = list(map(lambda x: int(x), auths.split(',')))
    
        if form.validate_on_submit():
            data=form.data
            role.name = data['name']
            role.auths = ','.join(map(lambda v:str(v), data['auths']))
    
            db.session.add(role)
            db.session.commit()
            flash('角色修改成功!', 'info')
        return render_template('admin/role_edit.html',form=form,role=role)

    修改对应的前端文件

    管理员管理

    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": "请输入管理员密码!",
                "required": "required"
            }
        )
    
        repwd = PasswordField(
            label='管理员重复密码',
            validators=[
                DataRequired("请输入管理员重复密码!"),
                EqualTo('pwd', message='两次密码不一致!'),
            ],
            description="管理员重复密码",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入管理员重复密码!",
                "required": "required"
            }
        )
    
        role_id=SelectField(
            label='所属角色',
            validators=[
                DataRequired("请选择角色!")
            ],
            coerce=int,
            choices=[(v.id, v.name) for v in roles],
            description="所属角色",
            render_kw={
                "class": "form-control",
            }
        )
    
        submit = SubmitField(
            '编辑',
            render_kw={
                "class": "btn btn-primary",
            }
        )
    添加管理员
    @admin.route('/admin/add/', methods=['GET', 'POST'])
    @admin_login_req
    def admin_add():
        form = AdminForm()
    
        from werkzeug.security import generate_password_hash
    
        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,
            )
    
            db.session.add(admin)
            db.session.commit()
    
            flash('管理员添加成功!', 'info')
    
        return render_template('admin/admin_add.html',form=form)
    管理员列表
    @admin.route('/admin/list/<int:page>/')
    @admin_login_req
    def admin_list(page=1):
        if page <= 0:
            page = 1
        page_data = Admin.query.join(
            Role
        ).filter(
            Role.id==Admin.role_id
        ).order_by(
            Admin.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/admin_list.html',page_data=page_data)

    修改对应的前端代码

    访问权限控制

    def admin_auth(func):
        @wraps(func)
        def decorated_function(*args, **kwargs):
            admin = Admin.query.join(
                Role
            ).filter(
                Role.id == Admin.role_id,
                Admin.id==session['admin_id']
            ).first()
    
            auths = admin.role.auths
            auths = list(map(lambda x: int(x), auths.split(',')))
    
            auth_list = Auth.query.all()
            urls = [v.url for v in auth_list for val in auths if val == v.id]
            rule = request.url_rule
    
            print(urls)
            print(rule)
    
            if str(rule) not in urls:
                abort(404)
            return func(*args, **kwargs)
        return decorated_function

    给视图函数添加装饰器,像这样

    @admin.route('/tag/list/<int:page>/')
    @admin_login_req
    @admin_auth
    def tag_list(page=1):
        ...

    转载于:https://www.cnblogs.com/gaoyongjian/p/10012130.html

    展开全文
  • flash("账户不存在!", "err") return redirect(url_for("home.login")) session["user"] = user.name session["user_id"] = user.id userlog = Userlog( user_id=user.id, ip=request.remote_addr ) db....

    会员模块实现

    会员注册

    class RegistForm(FlaskForm):
        name = StringField(
            label="昵称",
            validators=[
                DataRequired("昵称不能为空!")
            ],
            description="昵称",
            render_kw={
                "class": "form-control input-lg",
                "placeholder": "请输入昵称!",
            }
        )
        email = StringField(
            label="邮箱",
            validators=[
                DataRequired("邮箱不能为空!"),
                Email("邮箱格式不正确!")
            ],
            description="邮箱",
            render_kw={
                "class": "form-control input-lg",
                "placeholder": "请输入邮箱!",
            }
        )
        phone = StringField(
            label="手机",
            validators=[
                DataRequired("手机号不能为空!"),
                Regexp("1[34578]\d{9}", message="手机格式不正确!"),
                Length(min=11, max=11, message="手机长度不正确!")
            ],
            description="手机",
            render_kw={
                "class": "form-control input-lg",
                "placeholder": "请输入手机!",
            }
        )
        pwd = PasswordField(
            label="密码",
            validators=[
                DataRequired("密码不能为空!")
            ],
            description="密码",
            render_kw={
                "class": "form-control input-lg",
                "placeholder": "请输入密码!",
            }
        )
        repwd = PasswordField(
            label="确认密码",
            validators=[
                DataRequired("请输入确认密码!"),
                EqualTo('pwd', message="两次密码不一致!")
            ],
            description="确认密码",
            render_kw={
                "class": "form-control input-lg",
                "placeholder": "请输入确认密码!",
            }
        )
        submit = SubmitField(
            '注册',
            render_kw={
                "class": "btn btn-lg btn-success btn-block",
            }
        )
    
        def validate_name(self, field):
            name = field.data
            user = User.query.filter_by(name=name).count()
            if user == 1:
                raise ValidationError("昵称已经存在!")
    
        def validate_email(self, field):
            email = field.data
            user = User.query.filter_by(email=email).count()
            if user == 1:
                raise ValidationError("邮箱已经存在!")
    
        def validate_phone(self, field):
            phone = field.data
            user = User.query.filter_by(phone=phone).count()
            if user == 1:
                raise ValidationError("手机号码已经存在!")

    视图函数

    @home.route("/regist/", methods=["GET", "POST"])
    def regist():
        """
        会员注册
        """
        form = RegistForm()
        if form.validate_on_submit():
            data = form.data
            user = User(
                name=data["name"],
                email=data["email"],
                phone=data["phone"],
                pwd=generate_password_hash(data["pwd"]),
                uuid=uuid.uuid4().hex
            )
            db.session.add(user)
            db.session.commit()
            flash("注册成功!", "ok")
        return render_template("home/regist.html", form=form)

    修改对应的前端文件

    会员登录

    class LoginForm(FlaskForm):
        name = StringField(
            label="账号",
            validators=[
                DataRequired("账号不能为空!")
            ],
            description="账号",
            render_kw={
                "class": "form-control input-lg",
                "placeholder": "请输入账号!",
            }
        )
        pwd = PasswordField(
            label="密码",
            validators=[
                DataRequired("密码不能为空!")
            ],
            description="密码",
            render_kw={
                "class": "form-control input-lg",
                "placeholder": "请输入密码!",
            }
        )
        submit = SubmitField(
            '登录',
            render_kw={
                "class": "btn btn-lg btn-primary btn-block",
            }
        )

    视图函数
    在登录时需要校验密码,需要在User模型中添加check_pwd函数,和admin模型中的一样

    @home.route("/login/", methods=["GET", "POST"])
    def login():
        """
        登录
        """
        form = LoginForm()
        if form.validate_on_submit():
            data = form.data
            user = User.query.filter_by(name=data["name"]).first()
            if user:
                if not user.check_pwd(data["pwd"]):
                    flash("密码错误!", "err")
                    return redirect(url_for("home.login"))
            else:
                flash("账户不存在!", "err")
                return redirect(url_for("home.login"))
            session["user"] = user.name
            session["user_id"] = user.id
            userlog = Userlog(
                user_id=user.id,
                ip=request.remote_addr
            )
            db.session.add(userlog)
            db.session.commit()
            return redirect(url_for("home.user"))
        return render_template("home/login.html", form=form)

    在登录时添加登录日志
    修改对应的前端文件

    修改会员资料

    class UserdetailForm(FlaskForm):
        name = StringField(
            label="账号",
            validators=[
                DataRequired("账号不能为空!")
            ],
            description="账号",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入账号!",
            }
        )
        email = StringField(
            label="邮箱",
            validators=[
                DataRequired("邮箱不能为空!"),
                Email("邮箱格式不正确!")
            ],
            description="邮箱",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入邮箱!",
            }
        )
        phone = StringField(
            label="手机",
            validators=[
                DataRequired("手机号不能为空!"),
                Regexp("1[34578]\d{9}", message="手机格式不正确!"),
                Length(min=11, max=11, message="手机长度不正确!")
            ],
            description="手机",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入手机!",
            }
        )
        face = FileField(
            label="头像",
            validators=[
                DataRequired("请上传头像!")
            ],
            description="头像",
        )
        info = TextAreaField(
            label="简介",
            validators=[
                DataRequired("简介不能为空!")
            ],
            description="简介",
            render_kw={
                "class": "form-control",
                "rows": 10
            }
        )
        submit = SubmitField(
            '保存修改',
            render_kw={
                "class": "btn btn-success",
            }
        )

    视图函数
    修改文件名

    def change_filename(filename):
        """
        修改文件名称
        """
        fileinfo = os.path.splitext(filename)
        filename = datetime.datetime.now().strftime("%Y%m%d%H%M%S") + \
                   str(uuid.uuid4().hex) + fileinfo[-1]
        return filename
    
    
    def user_login_req(f):
        """
        登录装饰器
        """
    
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if "user" not in session:
                return redirect(url_for("home.login", next=request.url))
            return f(*args, **kwargs)
    
        return decorated_function
    @home.route("/user/", methods=["GET", "POST"])
    @user_login_req
    def user():
        form = UserdetailForm()
        user = User.query.get(int(session["user_id"]))
        form.face.validators = []
        if request.method == "GET":
            # 赋初值
            form.name.data = user.name
            form.email.data = user.email
            form.phone.data = user.phone
            form.info.data = user.info
        if form.validate_on_submit():
            data = form.data
            if form.face.data != "":
                file_face = secure_filename(form.face.data.filename)
                if not os.path.exists(app.config["FC_DIR"]):
                    os.makedirs(app.config["FC_DIR"])
                    os.chmod(app.config["FC_DIR"], 6)
                user.face = change_filename(file_face)
                form.face.data.save(app.config["FC_DIR"] + user.face)
    
            name_count = User.query.filter_by(name=data["name"]).count()
            if data["name"] != user.name and name_count == 1:
                flash("昵称已经存在!", "err")
                return redirect(url_for("home.user"))
    
            email_count = User.query.filter_by(email=data["email"]).count()
            if data["email"] != user.email and email_count == 1:
                flash("邮箱已经存在!", "err")
                return redirect(url_for("home.user"))
    
            phone_count = User.query.filter_by(phone=data["phone"]).count()
            if data["phone"] != user.phone and phone_count == 1:
                flash("手机已经存在!", "err")
                return redirect(url_for("home.user"))
    
            # 保存
            user.name = data["name"]
            user.email = data["email"]
            user.phone = data["phone"]
            user.info = data["info"]
            db.session.add(user)
            db.session.commit()
            flash("修改成功!", "ok")
            return redirect(url_for("home.user"))
        return render_template("home/user.html", form=form, user=user)

    在初始化文件中添加app.config["FC_DIR"] = os.path.join(os.path.abspath(os.path.dirname(__file__)), "static/uploads/users/")
    修改对应的前端文件

    修改密码

    class PwdForm(FlaskForm):
        old_pwd = PasswordField(
            label="旧密码",
            validators=[
                DataRequired("旧密码不能为空!")
            ],
            description="旧密码",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入旧密码!",
            }
        )
        new_pwd = PasswordField(
            label="新密码",
            validators=[
                DataRequired("新密码不能为空!"),
            ],
            description="新密码",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入新密码!",
            }
        )
        submit = SubmitField(
            '修改密码',
            render_kw={
                "class": "btn btn-success",
            }
        )

    视图函数

    @home.route("/pwd/", methods=["GET", "POST"])
    @user_login_req
    def pwd():
        """
        修改密码
        """
        form = PwdForm()
        if form.validate_on_submit():
            data = form.data
            user = User.query.filter_by(name=session["user"]).first()
            if not user.check_pwd(data["old_pwd"]):
                flash("旧密码错误!", "err")
                return redirect(url_for('home.pwd'))
            user.pwd = generate_password_hash(data["new_pwd"])
            db.session.add(user)
            db.session.commit()
            flash("修改密码成功,请重新登录!", "ok")
            return redirect(url_for('home.logout'))
        return render_template("home/pwd.html", form=form)

    修改对应的前端文件

    会员登录日志

    登陆日志不需要表单

    @home.route("/loginlog/<int:page>/", methods=["GET"])
    @user_login_req
    def loginlog(page=1):
        """
        会员登录日志
        """
        if page <= 0:
            page = 1
        page_data = Userlog.query.filter_by(
            user_id=int(session["user_id"])
        ).order_by(
            Userlog.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template("home/loginlog.html", page_data=page_data)

    新建app/templates/ui/home_page.html,用来分页

    {% macro page(data,url) -%}
        {% if data %}
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    <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>
            </nav>
        {% endif %}
    {%- endmacro %}

    修改对应的前端代码,并使用这个分页

    转载于:https://www.cnblogs.com/gaoyongjian/p/10029157.html

    展开全文
  • flash('权限添加成功!', 'info') return render_template('admin/auth_add.html',form=form) 权限列表 @admin.route('/auth/list/<int:page>/') @admin_login_req def auth_list(page=1): if page page = 1...

    基于角色的访问控制

    权限管理

    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",
            }
        )
    添加权限
    @admin.route('/auth/add/', methods=['GET', 'POST'])
    @admin_login_req
    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('权限添加成功!', 'info')
        return render_template('admin/auth_add.html',form=form)
    权限列表
    @admin.route('/auth/list/<int:page>/')
    @admin_login_req
    def auth_list(page=1):
        if page <= 0:
            page = 1
        page_data = Auth.query.order_by(
            Auth.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/auth_list.html',page_data=page_data)
    删除权限
    @admin.route('/auth/del/<int:id>/')
    @admin_login_req
    def auth_del(id=None):
        auth = Auth.query.get_or_404(int(id))
        db.session.delete(auth)
        db.session.commit()
        flash('权限删除成功!', 'info')
        return redirect(url_for('admin.auth_list', page=1))
    编辑权限
    @admin.route('/auth/edit/<int:id>/', methods=['GET', 'POST'])
    @admin_login_req
    def auth_edit(id=None):
        form = AuthForm()
        auth = Auth.query.get_or_404(int(id))
    
        if form.validate_on_submit():
            data = form.data
            auth.name =data['name']
            auth.url=data['url']
    
            db.session.add(auth)
            db.session.commit()
    
            flash('权限修改成功!', 'info')
            return redirect(url_for('admin.auth_edit', id=id))
        return render_template('admin/auth_edit.html',form=form, auth=auth)

    修改对应的前端文件

    角色管理

    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 auths],
            description='权限列表',
            render_kw={
                "class": "form-control",
            }
        )
        submit = SubmitField(
            '编辑',
            render_kw={
                "class": "btn btn-primary",
            }
        )
    添加角色
    @admin.route('/role/add/', methods=['GET', 'POST'])
    @admin_login_req
    def role_add():
        form = RoleForm()
        if form.validate_on_submit():
            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('角色添加成功!', 'info')
        return render_template('admin/role_add.html',form=form)
    角色列表
    @admin.route('/role/list/<int:page>/')
    @admin_login_req
    def role_list(page=1):
        if page <= 0:
            page = 1
        page_data = Role.query.order_by(
            Role.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/role_list.html',page_data=page_data)
    删除角色
    @admin.route('/role/del/<int:id>/')
    @admin_login_req
    def role_del(id=None):
        role = Role.query.get_or_404(int(id))
        db.session.delete(role)
        db.session.commit()
        flash('角色删除成功!', 'info')
        return redirect(url_for('admin.role_list', page=1))
    修改权限
    @admin.route('/role/edit/<int:id>/', methods=['GET', 'POST'])
    @admin_login_req
    def role_edit(id=None):
        form = RoleForm()
        role = Role.query.get_or_404(int(id))
    
        if request.method == 'GET':
            auths = role.auths
            form.auths.data = list(map(lambda x: int(x), auths.split(',')))
    
        if form.validate_on_submit():
            data=form.data
            role.name = data['name']
            role.auths = ','.join(map(lambda v:str(v), data['auths']))
    
            db.session.add(role)
            db.session.commit()
            flash('角色修改成功!', 'info')
        return render_template('admin/role_edit.html',form=form,role=role)

    修改对应的前端文件

    管理员管理

    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": "请输入管理员密码!",
                "required": "required"
            }
        )
    
        repwd = PasswordField(
            label='管理员重复密码',
            validators=[
                DataRequired("请输入管理员重复密码!"),
                EqualTo('pwd', message='两次密码不一致!'),
            ],
            description="管理员重复密码",
            render_kw={
                "class": "form-control",
                "placeholder": "请输入管理员重复密码!",
                "required": "required"
            }
        )
    
        role_id=SelectField(
            label='所属角色',
            validators=[
                DataRequired("请选择角色!")
            ],
            coerce=int,
            choices=[(v.id, v.name) for v in roles],
            description="所属角色",
            render_kw={
                "class": "form-control",
            }
        )
    
        submit = SubmitField(
            '编辑',
            render_kw={
                "class": "btn btn-primary",
            }
        )
    添加管理员
    @admin.route('/admin/add/', methods=['GET', 'POST'])
    @admin_login_req
    def admin_add():
        form = AdminForm()
    
        from werkzeug.security import generate_password_hash
    
        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,
            )
    
            db.session.add(admin)
            db.session.commit()
    
            flash('管理员添加成功!', 'info')
    
        return render_template('admin/admin_add.html',form=form)
    管理员列表
    @admin.route('/admin/list/<int:page>/')
    @admin_login_req
    def admin_list(page=1):
        if page <= 0:
            page = 1
        page_data = Admin.query.join(
            Role
        ).filter(
            Role.id==Admin.role_id
        ).order_by(
            Admin.addtime.desc()
        ).paginate(page=page, per_page=10)
        return render_template('admin/admin_list.html',page_data=page_data)

    修改对应的前端代码

    访问权限控制

    def admin_auth(func):
        @wraps(func)
        def decorated_function(*args, **kwargs):
            admin = Admin.query.join(
                Role
            ).filter(
                Role.id == Admin.role_id,
                Admin.id==session['admin_id']
            ).first()
    
            auths = admin.role.auths
            auths = list(map(lambda x: int(x), auths.split(',')))
    
            auth_list = Auth.query.all()
            urls = [v.url for v in auth_list for val in auths if val == v.id]
            rule = request.url_rule
    
            print(urls)
            print(rule)
    
            if str(rule) not in urls:
                abort(404)
            return func(*args, **kwargs)
        return decorated_function

    给视图函数添加装饰器,像这样

    @admin.route('/tag/list/<int:page>/')
    @admin_login_req
    @admin_auth
    def tag_list(page=1):
        ...

    转载于:https://www.cnblogs.com/gaoyongjian/p/10029148.html

    展开全文
  • 程序是运行在flash中还是RAM中?

    千次阅读 2018-03-17 22:37:05
    最近在做项目中遇到一些疑虑,包括OTA升级时会不会阻塞到其他工作线程、select原理和正确用法、如何快速正确理解产品到软件框架构建、嵌入式应用的代码优化方法。本篇文章主要针对第一个问题,请教外援,他解释:...
    前言

    最近在做项目中遇到一些疑虑,包括OTA升级时会不会阻塞到其他工作线程、select原理和正确用法、如何快速正确理解产品到软件框架构建、嵌入式应用的代码优化方法。本篇文章主要针对第一个问题,请教外援,他解释:正常情况下代码是在OTA1中运行的,当OTA时程序下载固件到OTA2成功后从flash中OTA2对应地址启动。当时觉得不对劲,程序怎么会在flash中运行?查了下,对于x86的pc机和单片机等嵌入式开发系统程序的存储是截然相反的。

    x86cpu和单片机读取程序的具体途径

    x86的PC机cpu在运行时程序是存储在RAM中,而单片机等嵌入式系统则是存在flash中的。
    pc机在运行程序的时候将程序从外存(硬盘)中,调入到RAM中运行,cpu从RAM中读取程序和数据;而单片机的程序则是固化在flash中,cpu运行时直接从flash中读取程序,从RAM中读取数据 。

    原因分析

    x86构架的cpu是基于冯.诺依曼体系的,即数据和程序存储在一起,而且pc机的RAM资源相当丰富,从几十M到几百M甚至是几个G,客观上能够承受大量的程序数据。
    单片机的构架大多是哈弗体系的,即程序和数据分开存储,而且单片的片内RAM资源是相当有限的,内部的RAM过大会带来成本的大幅度提高。
    冯.诺依曼体系与哈佛体系的区别:
    二者的区别就是程序空间和数据空间是否是一体的。 早期的微处理器大多采用冯诺依曼结构,典型代表是Intel公司的X86微处理器。取指令和取操作数都在同一总线上,通过分时复用的方式进行的。缺点是在高速运行时,不能达到同时取指令和取操作数,从而形成了传输过程的瓶颈。
    哈佛总线技术应用是以DSP和ARM为代表的。采用哈佛总线体系结构的芯片内部程序空间和数据空间是分开的,这就允许同时取指令和取操作数,从而大大提高了运算能力。
    例如STM320LF240x系列DSP是增强型的哈佛结构通过三组并行的总线访问多个存储空间。它们分别是:程序地址总线(PAB),数据地址读总线(DRAB)和数据地址写总线(DWRB)。

    小结

    STM32支持两种方式,它是由两个引脚来控制启动方式的,通常是下载到flash启动;用jlink在线仿真,则是下载到SRAM中,无需改变启动方式SRAM掉电后程序会自动消失。可参考下述理解的更详细,后续嵌入式代码优化、框架设计也积累到一些经验后续再分享。
    参考 :
    cpu运行时程序是在flash中还是在RAM呢?
    讨论:程序是运行在flash中还是Ram中呢?
    程序在flash中还是ram中运行

    展开全文
  • <a href=""><b>电影管理系统</b></a> <p class="login-box-msg"></p> 请输入账号!"> <span class="glyphicon glyphicon-envelope form-control-feedback"></span> ...
  • 电影模块实现 上映预告 @home.route("/animation/") def animation(): """ 首页轮播动画 """ data = Preview.query.all() for v in data: v.id = v.id - 1 return render_template("home/anima...
  • 芯片和谐 v1-08。 encx24j600+spi flash 的演示。 这个演示也适用于使用 tls v1-2 与谷歌服务器通信的电子邮件演示。 您将需要 PIM(pic32mx795f512l)、Explorer 16、pictail plus ssd1926 和快速 100mbps 以太网 ...
  • flash("添加评论成功!", "ok") return redirect(url_for('home.play', id=movie.id, page=1)) # 放在后面避免添加评论播放量涨2 movie.playnum = movie.playnum + 1 db.session.add(movie) db.session.commit...
  • 电影 ('static', filename='base/images/logo.png') }}"> ('static', filename='base/css/bootstrap.min.css') }}"> ('static', filename='base/css/bootstrap-movie.css') }}"> ('static', filename='base/...
  • 可以使用Qt Creator构建该项目。 只需导入并按建造。 然后运行该应用程序,并使用GUI将固件下载到目标或从目标上载固件。 将您的控制器置于UART引导模式。 连接USB / UART 转换器连接到控制器的各个引脚。
  • uClinux下Nor Flash的JFFS2文件系统构建

    千次阅读 2012-04-24 15:36:31
    目前的嵌入式系统多使用FLASH作为主存,因此,如何有效管理FLASH上的数据非常重要。文章以SST39VF160芯片为例,讨论了在Nor Flash上建立uClinux的JFFS2文件系统的一般步骤,从而为FLASH上的数据管理提供了理想的选择方式...
  • 该系统硬件设计采用RISC型32位处理器S3C44B0X,以太网控制器RTL8019AS,2 MB的NOR Flash及8 MB的SDRAM。通过配置μClinux嵌入式操作系统及BOA服务器构建了基于嵌入式的Web服务器。通过编写设备驱动程序和服务器CGI...
  • 螺旋测flash 什么是Micrometer? Micrometer是一个简单的外观,用于以供应商中立的方式收集Java应用程序中的指标。 您可以考虑使用SLF4J作为指标。 Micrometer内置了对许多不同指标后端的内置支持,包括Atlas...
  • With all the hype around Flash’s ability to communicate with servers to build “Rich Internet Applications”, many people seem to have forgotten some of Flash’s native abilities. Sadly, new ...
  • 在云计算、大数据等新一代信息技术推动下,全球IT...我国厂商应把握新市场新技术带来的机遇,构建自主创新产业生态,实现产业由大到强的转变。 国产整机厂商快速崛起 根据Gartner数据显示,2015年全球服务器出货1...
  • 该工具将协助以Flash为基础单芯片Actel FPGA引进全新ARM7系列软IP处理器CoreMP7的开发。CoreConsole IDP能让用户专注于系统而非个别元件,因此可及早进行系统级评估,缩短整个系统的开发时间。 采用Actel的...
  • 前言再小的技术点也会有他的市场!...在萤石/乐橙/吼/趣看类型直播应用大规模开展的今天,高大上的直播形态视乎占据了主流,然而这些对于普通型的公司似乎成本有点高,而且不能够长线、无忧地进行,我所
  • 在c中对flash读写可以实现了,下面就是网络服务器的构建了,这里用到了lwip协议栈,据说是瑞典科学院一般人弄的,很适合在嵌入式系统中做网络传输。只要在服务器端监听客户端连接并解析客户端传来的数据就行了。比如...
  • Python是一门非常友好的语言,学习成本很低,这也是我很喜欢写Python的原因之一,在与应用端或者是业务端做整合的时候我们经常会将模型或者是数据分析的应用做成可以被直接调用的web服务来提供外部的访问,在web服务...
  • 外媒 Windows Latest 报道,微软推出的一款新的更新补丁正在向 Windows 10 版本 20H2、2004 及以上版本推出,以永久删除 Adobe Flash Player。据说 Windows 10 KB4577586 是可选的更新,但当用户点击 “检查更新”...
  • 高级半导体解决方案领导厂商瑞萨电子株式会社(TSE:6723)今天宣布推出面向汽车车身应用的RH850/F1x系列32位控制器(MCU),它是RH850系列汽车MCU的首款产品,配置了采用业内最先进40 nm工艺的嵌入式Flash存储器...
  • 嵌入式linux下常见的文件系统 • RomFS:只读文件系统,可以放在ROM空间,也 ...• JFFS/JFFS2:为Flash设计的日志文件系统 • Yaffs:专门为Nand Flash设计 • proc:为内核和内核模块将信息发送给进
  • As recently as seven short years ago, building video applications on the web was a massive ... Remember the days of using Flash and proprietary codecs (which often required licensing)? Yuck. In the ...
  • SPIFlashProgrammer是一块小巧但功能强大的电路板,其中装有德州仪器(TI)的Tiva-C系列ARM处理器,两个在生产环境中使用的闪存设备,以允许一个电路板在生产线上对多达两个不同的目标设备进行编程,以及用于供电...
  • flash进行分类,第二个参数指定flash信息的分类 mark 添加弹窗alert mark 标签的分页展示 前往views中的标签列表进行查询以及分页。 @admin.route("/tag/list/<int:page>/", methods= [...
  • 核心器件: MSP430 在现代便携式智能仪器或手持设备中,中文人机界面成为一种事实上的行业标准。能显示汉字的图形点阵液晶和可输入数字的小键盘已成为智能设备必不可少的组成... 一、MSP430系列FLASH型单片机的功耗
  • 在现代便携式智能仪器或手持设备中,中文人机界面成为一种事实上的行业标准。能显示汉字的图形点阵液晶和可输入数字的小键盘已成为智能设备必不可少的组成部分。...一、MSP430系列FLASH型单片机的功耗特点

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,306
精华内容 2,122
关键字:

flask构建微服务