Flask 构建微电影视频网站(四)

后台管理

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

管理员登录

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

from flask_sqlalchemy import SQLAlchemyapp = 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, ValidationErrorfrom app.models import Adminclass 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.dataadmin = 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.dataadmin = 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_hashreturn check_password_hash(self.pwd, pwd)

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

    {% for message in get_flashed_messages() %}{% endfor %}
{{ form.account }}{% for err in form.account.errors %}{{ err }}{% endfor %}{{ form.pwd }}{% for err in form.pwd.errors %}{{ err }}{% endfor %}{{ form.submit }}{{ form.csrf_token }}
标签管理

创建一个表单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.datatag = 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)

修改前端代码

{% for message in get_flashed_messages(category_filter=['info']) %}

操作成功!

{{ message }}{% endfor %}{% for message in get_flashed_messages(category_filter=['error']) %}

操作失败!

{{ message }}{% endfor %}{{ form.name }}{% for err in form.name.errors %}{{ err }}{% endfor %}{{ form.submit }}{{ form.csrf_token }}
标签列表

视图函数

@admin.route('/tag/list//')
@admin_login_req
def tag_list(page=1):if page <= 0:page = 1page_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)

修改前端代码

{% for message in get_flashed_messages(category_filter=['info']) %}

操作成功!

{{ message }}{% endfor %}{% for tag in page_data.items %}{% endfor %}
编号名称添加时间操作事项
{{ tag.id }}{{ tag.name }}{{ tag.addtime }}编辑 删除

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

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

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

在标签列表中使用这个macro

{% extends 'admin/admin.html' %}
{% from 'ui/admin_page.html' import pagination %}...{{ pagination(page_data, 'admin.tag_list') }}
删除标签

视图函数

@admin.route('/tag/del//')
@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标签

删除
修改标签

视图函数

@admin.route('/tag/edit//', 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.datatag_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,用来进行标签的修改
代码和添加标签中的几乎一致,只是需要显示标签的名字

{{ form.name(value=tag.name) }}{% for err in form.name.errors %}{{ err }}{% endfor %}
电影管理

新建电影表单
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.datanum = 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_filenamedef 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.datafile_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 %}

微电影管理系统

添加电影

{% for message in get_flashed_messages(category_filter=['info']) %}

操作成功!

{{ message }}{% endfor %}{{ form.title }}{% for err in form.title.errors %}{{ err }}{% endfor %}{{ form.url }}{% for err in form.url.errors %}{{ err }}{% endfor %} {# #}{{ form.info }}{% for err in form.info.errors %}{{ err }}{% endfor %}{{ form.logo }}{% for err in form.logo.errors %}{{ err }}{% endfor %} {# #}{{ form.star }}{% for err in form.star.errors %}{{ err }}{% endfor %}{{ form.tag_id }}{% for err in form.tag_id.errors %}{{ err }}{% endfor %}{{ form.area }}{% for err in form.area.errors %}{{ err }}{% endfor %}{{ form.length }}{% for err in form.length.errors %}{{ err }}{% endfor %}{{ form.release_time }}{% for err in form.release_time.errors %}{{ err }}{% endfor %}{{ form.csrf_token }}{{ form.submit }}
{% endblock %}
电影列表

视图函数

@admin.route('/movie/list//')
@admin_login_req
def movie_list(page=1):if page <= 0:page = 1page_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 %}

微电影管理系统

电影列表

{% for message in get_flashed_messages(category_filter=['info']) %}

操作成功!

{{ message }}{% endfor %}{% for data in page_data.items %}{% endfor %}
编号片名片长标签地区星级播放数量评论数量上映时间操作事项
{{ data.id }}{{ data.title }}{{ data.length }}分钟{{ data.tag.name }}{{ data.area }}{{ data.star }}{{ data.playnum }}{{ data.commentnum }}{{ data.release_time }}编辑 删除
{{ pagination(page_data, 'admin.movie_list') }}
{% endblock %}{% block js %} {% endblock %}

修改app/templates/admin/grid.html

  • 电影列表
  • 删除电影

    视图函数

    @admin.route('/movie/del//')
    @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/', 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.infoform.tag_id.data = movie.tag_idform.star.data = movie.starif form.validate_on_submit():data = form.datamovie_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 %}

    微电影管理系统

    修改电影

    {% for message in get_flashed_messages(category_filter=['info']) %}

    操作成功!

    {{ message }}{% endfor %}{% for message in get_flashed_messages(category_filter=['error']) %}

    操作失败!

    {{ message }}{% endfor %}{{ form.title(value=movie.title) }}{% for err in form.title.errors %}{{ err }}{% endfor %}{{ form.url }}{% for err in form.url.errors %}{{ err }}{% endfor %}{{ form.info }}{% for err in form.info.errors %}{{ err }}{% endfor %}{{ form.logo }}{% for err in form.logo.errors %}{{ err }}{% endfor %}{{ form.star }}{% for err in form.star.errors %}{{ err }}{% endfor %}{{ form.tag_id }}{% for err in form.tag_id.errors %}{{ err }}{% endfor %}{{ form.area(value=movie.area) }}{% for err in form.area.errors %}{{ err }}{% endfor %}{{ form.length(value=movie.length) }}{% for err in form.length.errors %}{{ err }}{% endfor %}{{ form.release_time(value=movie.release_time) }}{% for err in form.release_time.errors %}{{ err }}{% endfor %}{{ form.csrf_token }}{{ form.submit }}
    {% endblock %}{% block js %} {% endblock %}

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

    编辑
    预告管理

    创建预告表单

    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.datanum = 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.datafile_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 %}

    微电影管理系统

    添加预告

    {% for message in get_flashed_messages(category_filter=['info']) %}

    操作成功!

    {{ message }}{% endfor %}{% for message in get_flashed_messages(category_filter=['error']) %}

    操作失败!

    {{ message }}{% endfor %}{{ form.title }}{% for err in form.title.errors %}{{ err }}{% endfor %}{{ form.logo }}{% for err in form.logo.errors %}{{ err }}{% endfor %}{{ form.csrf_token }}{{ form.submit }}
    {% endblock %}{% block js %} {% endblock %}
    预告列表

    视图函数

    @admin.route('/preview/list//')
    @admin_login_req
    def preview_list(page=1):if page <= 0:page = 1page_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 %}

    微电影管理系统

    预告列表

    {% for message in get_flashed_messages(category_filter=['info']) %}

    操作成功!

    {{ message }}{% endfor %}{% for data in page_data.items %}{% endfor %}
    编号预告标题预告封面添加时间操作事项
    {{ data.id }}{{ data.title }}{{ data.addtime }}编辑 删除
    {{ pagination(page_data, 'admin.preview_list') }}
    {% endblock %}{% block js %} {% endblock %}

    修改app/templates/admin/grid.html

  • 预告列表
  • 删除预告

    视图函数

    @admin.route('/preview/del//')
    @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//', 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.titleif form.validate_on_submit():data = form.dataif 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,代码拷贝添加预告,修改部分

    {{ form.title(value=preview.title) }}{% for err in form.title.errors %}{{ err }}{% endfor %}
    
    {{ form.logo }}{% for err in form.logo.errors %}{{ err }}{% endfor %}
    
    会员管理
    会员列表
    @admin.route('/user/list//')
    @admin_login_req
    def user_list(page=1):if page <= 0:page = 1page_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 %}

    微电影管理系统

    会员列表

    {% for message in get_flashed_messages(category_filter=['info']) %}

    操作成功!

    {{ message }}{% endfor %}{# #}{% for data in page_data.items %}{# #}{% endfor %}
    编号昵称邮箱手机头像状态注册时间操作事项
    {{ data.id }}{{ data.name }}{{ data.email }}{{ data.phone }}正常/冻结{{ data.addtime }}查看{#  #}{# 删除
    {{ pagination(page_data, 'admin.preview_list') }}
    {% endblock %}{% block js %} {% endblock %}
    查看会员
    @admin.route('/user/view//')
    @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)
    编号:1
    昵称:{{ user.name }}
    邮箱:{{ user.email }}
    手机:{{ user.phone }}
    头像:
    注册时间:{{ user.addtime }}
    唯一标志符:{{ user.uuid }}
    个性简介:{{ user.info }}
    删除用户
    @admin.route('/user/del//')
    @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//')
    @admin_login_req
    def comment_list(page=1):if page <= 0:page = 1page_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)

    评论列表

    {% for message in get_flashed_messages(category_filter=['info']) %}

    操作成功!

    {{ message }}{% endfor %}{% for data in page_data.items %}User Image{{ data.user.name }} {{ data.addtime }}关于电影删除{% endfor %}{{ pagination(page_data, 'admin.preview_list') }}
    删除评论
    @admin.route('/comment/del//')
    @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//')
    @admin_login_req
    def moviecol_list(page=1):if page <= 0:page = 1page_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)

    收藏列表

    {% for message in get_flashed_messages(category_filter=['info']) %}

    操作成功!

    {{ message }}{% endfor %}{% for data in page_data.items %}{% endfor %}
    编号电影用户添加时间操作事项
    {{ data.id }}{{ data.movie.title }}{{ data.user.name }}{{ data.addtime }}{# 删除
    {{ pagination(page_data, 'admin.moviecol_list') }}
    删除收藏
    @admin.route('/moviecol/del//')
    @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 sessionpwd = field.dataname = 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.dataadmin = Admin.query.filter_by(name=session['admin']).first()from werkzeug.security import generate_password_hashadmin.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']) %}{% endfor %}{% for message in get_flashed_messages(category_filter=['error']) %}{% endfor %}

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

    日志管理
    @admin.route('/oplog/list//')
    @admin_login_req
    def oplog_list(page=1):if page <= 0:page = 1page_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//')
    @admin_login_req
    def adminloginlog_list(page=1):if page <= 0:page = 1page_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//')
    @admin_login_req
    def userloginlog_list(page=1):if page <= 0:page = 1page_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.dataauth = 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//')
    @admin_login_req
    def auth_list(page=1):if page <= 0:page = 1page_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//')
    @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//', 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.dataauth.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.datarole = 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//')
    @admin_login_req
    def role_list(page=1):if page <= 0:page = 1page_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//')
    @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//', 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.authsform.auths.data = list(map(lambda x: int(x), auths.split(',')))if form.validate_on_submit():data=form.datarole.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_hashif form.validate_on_submit():data = form.dataadmin = 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//')
    @admin_login_req
    def admin_list(page=1):if page <= 0:page = 1page_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.authsauths = 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_ruleprint(urls)print(rule)if str(rule) not in urls:abort(404)return func(*args, **kwargs)return decorated_function

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

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

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


    本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

    相关文章

    立即
    投稿

    微信公众账号

    微信扫一扫加关注

    返回
    顶部