Flask开发微电影网站(六)


1. 后台管理登录功能实现

1.1 后台管理页面登录表单LoginForm

在app的admin目录下创建forms.py文件,用来保存admin蓝图中需要使用到的表单

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, FileField, TextAreaField, SelectField, SelectMultipleField
from wtforms.validators import DataRequired, ValidationError, EqualTo
from app.models import Admin, Tag, Auth, Role

tags = Tag.query.all()             # 获取数据库中所有的电影标签
auth_list = Auth.query.all()       # 获取数据库中所有的权限列表
role_list = Role.query.all()       # 获取数据库中所有的角色列表

# 登录表单
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
        user = Admin.query.filter_by(name=account).count()
        if user == 0:
            raise ValidationError("账号不存在!请重新输入!!")

1.2 后台管理登录页面视图函数

在登录视图函数中调用登录表单LoginForm

# 登录
@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.get("pwd")):
            flash("旧密码错误,请重新输入!", "err")
            return redirect(url_for("admin.login"))

        session['admin'] = data.get("account")
        session['admin_id'] = admin.id
        adminlog = Adminlog(
            admin_id=admin.id,
            ip=request.remote_addr
        )
        db.session.add(adminlog)
        db.session.commit()
        return redirect(request.args.get("next") or url_for('admin.index'))
    return render_template("admin/login.html", form=form)

1.3 后台管理登录页面前端页面

登录页面中调用后台登录视图函数返回来的变量form

form变量中包含管理员登录需要的字段




    
    
    微电影管理系统
    
    
    
    
    
    
    








2. 后台管理页面退出功能实现

2.1 后台管理页面退出视图函数

退出功能必须要用户登录才能有效,所以要用到登录控制装饰器

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

3. 后台管理页面主页功能实现

3.1 后台管理页面主页视图函数

后台管理员必须要登录进行密码验证才能打开后台管理页面,同时用户要用相应的权限才能打开后台管理页面的主页面

所以后台管理主页视图函数必须被登录控制装饰器和权限控制装饰器同时装饰

@admin.route('/')
@admin_login_req
@admin_auth
def index():
    return render_template("admin/index.html")

3.2 后台管理页面主页前端页面

由于在admin.html页面中已经导入左侧菜单部分,所以后台管理页面主页继承admin.html页面实现顶端部分和左侧菜单栏

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

{% block content %}
    

微电影管理系统

内存使用率

系统设置

{% endblock %} {% block js %} {% endblock %}

4. 后台管理页面修改密码功能实现

4.1 后台管理页面修改密码表单

在app的admin目录下的forms.py文件中,定义修改密码的表单

# 修改密码表单
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": "请输入新密码!"
        }
    )
    summit = SubmitField(
        "编辑",
        render_kw={
            "class": "btn btn-primary",
        }
    )

    def validate_old_pwd(self, field):
        from flask import session
        pwd = field.data
        name = session.get("admin")
        admin = Admin.query.filter_by(name=name).first()

        if not admin.check_pwd(pwd):
            raise ValidationError("旧密码错误!")

4.2 后台管理页面修改密码视图函数

修改密码必须要登录,所以要用登录控制装饰器装饰修改密码的视图函数权限控制装饰器进行管理用户权限判断

# 修改密码
@admin.route('/pwd/', methods=['GET', 'POST'])
@admin_login_req
@admin_auth
def pwd():
    form = PwdForm()
    if form.validate_on_submit():
        data = form.data
        admin = Admin.query.filter_by(name=session.get("admin")).first()

        from werkzeug.security import generate_password_hash
        admin.pwd = generate_password_hash(data.get("new_pwd"))
        db.session.add(admin)
        db.session.commit()
        flash("修改密码成功,请重新登录!", "ok")
        return redirect(url_for("admin.logout"))
    return render_template("admin/pwd.html", form=form)

4.3 后台管理页面前端页面

由于在admin.html页面中已经导入左侧菜单部分,所以后台管理页面主页继承admin.html页面实现顶端部分和左侧菜单栏

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

{% block content %}
    
    

微电影管理系统

修改密码

{{ form.old_pwd }} {% for err in form.old_pwd.errors %}
{{ err }}
{% endfor %}
{{ form.new_pwd }} {% for err in form.new_pwd.errors %}
{{ err }}
{% endfor %}
{% endblock %}

5. 后台管理之电影标签管理

5.1 后台管理页面标签表单

在app的admin目录下的forms.py文件中创建TagForm表单,用来保存标签的表单信息

# 标签表单
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'
        }
    )

5.2 前端页面分页组件

在templates目录下创建ui目录,在ui目录下创建admin_page.html页面,用来保存后台管理页面分页组件代码

{% macro page(data,url) -%}
    {% if data %}
        
    {% endif %}
{%- endmacro %}

5.3 电影标签管理之标签列表功能实现

5.3.1 电影标签管理标签列表页面视图函数

用控制装饰器来进行登录管理,用权限控制装饰器来进行后台管理用户判断

@admin.route("/tag/list//", methods=["GET"])
@admin_login_req
@admin_auth
def tag_list(page=None):
    """
    标签列表
    """
    if page is None:
        page = 1
    page_data = Tag.query.order_by(
        Tag.addtime.desc()
    ).paginate(page=page, per_page=1)
    return render_template("admin/tag_list.html", page_data=page_data)

5.3.2 电影标签管理标签列表页面前端页面

由于在admin.html页面中已经导入左侧菜单部分,所以后台管理页面主页继承admin.html页面实现顶端部分和左侧菜单栏

导入admin_page.html来实现电影标签的分页展示

{% extends 'admin/admin.html' %}
{% import 'ui/admin_page.html' as pg %}

{% block content %}
    
    

微电影管理系统

标签列表

{% for msg in get_flashed_messages(category_filter=["ok"]) %}

操作成功

{{ msg }}
{% endfor %} {% for v in page_data.items %} {% endfor %}
编号 名称 添加时间 操作事项
{{ v.id }} {{ v.name }} {{ v.addtime }} 编辑   删除
{% endblock %} {% block js %} {% endblock %}

5.4 电影标签管理之添加电影标签功能实现

5.4.1 后台管理页面添加标签视图函数

# 添加标签
@admin.route('/tag/add/', methods=['GET', 'POST'])
@admin_login_req
@admin_auth
def tag_add():
    form = TagForm()
    if form.validate_on_submit():
        data = form.data
        tag = Tag.query.filter_by(name=data.get("name")).count()
        if tag == 1:
            flash("标签名称已存在,请重新输入!", "err")
            return redirect(url_for("admin.tag_add"))
        # tag = Tag(name=data["name"])
        tag = Tag(name=data.get("name"))
        db.session.add(tag)
        db.session.commit()
        flash("添加标签成功!", "ok")
        oplog = Oplog(
            admin_id=session.get("admin_id"),
            ip=request.remote_addr,
            reason="添加标签:%s" % data.get("name")
        )
        db.session.add(oplog)
        db.session.commit()
        return redirect(url_for("admin.tag_list", page=1))
    return render_template("admin/tag_add.html", form=form)

5.2.3 后台管理页面添加标签前端页面

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

{% block content %}
    
    

微电影管理系统

添加标签

{% for msg in get_flashed_messages(category_filter=["ok"]) %}

操作成功

{{ msg }}
{% endfor %} {% for msg in get_flashed_messages(category_filter=["err"]) %}

操作失败

{{ msg }}
{% endfor %}
{{ form.name }} {% for err in form.name.errors %}
{{ err }}
{% endfor %}
{% endblock %} {% block js %} {% endblock %}

5.3 电影标签管理之编辑电影标签功能实现

5.3.1 电影标签管理之编辑电影标签视图函数

# 编辑标签
@admin.route('/tag/edit//', methods=["GET", "POST"])
@admin_login_req
@admin_auth
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.get("name")).count()
        if tag.name != data.get("name") and tag_count == 1:
            flash("标签名称已存在,请重新输入!", "err")
            return redirect(url_for("admin.tag_edit", id=id))
        # tag = Tag(name=data["name"])
        tag.name = data.get("name")
        db.session.add(tag)
        db.session.commit()
        flash("修改标签成功!", "ok")
        return redirect(url_for("admin.tag_list", page=1))
    return render_template("admin/tag_edit.html", form=form, tag=tag)

5.3.1 电影标签管理之编辑电影标签前端页面

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

{% block content %}
    
    

微电影管理系统

修改标签

{% for msg in get_flashed_messages(category_filter=["ok"]) %}

操作成功

{{ msg }}
{% endfor %} {% for msg in get_flashed_messages(category_filter=["err"]) %}

操作失败

{{ msg }}
{% endfor %}
{{ form.name(value=tag.name) }} {% for err in form.name.errors %}
{{ err }}
{% endfor %}
{% endblock %} {% block js %} {% endblock %}

5.3 电影标签管理之删除电影标签功能实现

5.3.1 电影标签管理之删除电影标签视图函数

	# 标签删除
	@admin.route('/tag/del//', methods=["GET"])
	@admin_login_req
	@admin_auth
	def tag_del(id=None):
	    tag = Tag.query.filter_by(id=id).first_or_404()
	    db.session.delete(tag)
	    db.session.commit()
	    flash("删除标签成功!", "ok")
	    return redirect(url_for("admin.tag_list", page=1))