2.标签管理
2.1标签的添加以及增删改查的forms表单
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
class BaseForm(FlaskForm):
name = StringField(
label="标签名",
validators=[
DataRequired()
]
)
class TagForm(BaseForm):
submit = SubmitField(
label="添加标签"
)
class EditTagForm(BaseForm):
submit = SubmitField(
label="编辑标签"
)
2.2标签的视图函数
from app import app, db
from flask import render_template, flash, redirect, url_for,request
from app.admin import admin
from app.admin.forms.tag import TagForm, EditTagForm
from app.admin.utils import write_adminlog, permission_control, is_admin_login
from app.models import Tag
@admin.route('/tag/list/')
@admin.route('/tag/list//')
@is_admin_login
@permission_control
def tag_list(page=1):
tagsPageObj = Tag.query.paginate(page, per_page=app.config['PER_PAGE'])
return render_template('admin/tag/list.html',
tagsPageObj=tagsPageObj)
@admin.route('/tag/add/', methods=['POST', 'GET'])
@is_admin_login
@permission_control
def tag_add():
form = TagForm()
if form.validate_on_submit():
name = form.name.data
# 判断添加的标签是否存在?
tag = Tag.query.filter_by(name=name).first()
if tag:
flash("标签%s已经存在" % (tag.name))
return redirect(url_for('admin.tag_add'))
tag = Tag(name=name)
db.session.add(tag)
db.session.commit()
flash("标签%s添加成功" % (tag.name))
# ******将添加标签的操作记录到数据库中
write_adminlog("标签%s添加成功" % (tag.name))
return redirect(url_for('admin.tag_add'))
return render_template('admin/tag/add.html',
form=form)
@admin.route('/tag/edit//', methods=['POST', 'GET'])
@is_admin_login
@permission_control
def tag_edit(id):
form = EditTagForm()
tag = Tag.query.filter_by(id=id).first_or_404()
old_tagname = tag.name
form.name.data = tag.name
if form.validate_on_submit():
name = request.form['name']
# 判断要更新的标签名是否已经存在?
if name != tag.name and Tag.query.filter_by(name=name).first():
flash("标签%s已经存在" % (name))
return redirect(url_for('admin.tag_list', page=1))
tag.name = name
db.session.add(tag)
db.session.commit()
flash("更新标签为%s成功!" % (name), category='ok')
write_adminlog("更新标签(%s)为%s成功!" % (old_tagname, name))
return redirect(url_for('admin.tag_list', page=1))
return render_template('admin/tag/edit.html',
form=form)
@admin.route('/tag/delete//')
@is_admin_login
@permission_control
def tag_del(id):
if id:
tag = Tag.query.filter_by(id=id).first_or_404()
db.session.delete(tag)
db.session.commit()
# 删除后闪现消息
flash('删除标签%s成功!' % (tag.name), category='ok')
write_adminlog('删除标签%s成功!' % (tag.name))
return redirect(url_for('admin.tag_list', page=1))
2.3标签的页面实现
## 增加标签的页面
{% extends 'admin/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}添加标签{% endblock %}
{% block content %}
{# 面板 #}
添加标签
{{ wtf.quick_form(form) }}
{% endblock %}
## 修改标签等的页面
{% extends 'admin/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}编辑标签{% endblock %}
{% block content %}
{# 面板 #}
编辑标签
{{ wtf.quick_form(form) }}
{% endblock %}
## 展示标签的页面,即标签列表
{% extends 'admin/base.html' %}
{% block title %} 标签列表{% endblock %}
{% block content %}
标签列表
{# 登录日志表格#}
编号
名称
添加时间
操作事项
{% for v in tagsPageObj.items %}
{{ v.id }}
{{ v.name }}
{{ v.addtime }}
{# 编辑按钮 #}
编辑
{# 删除按钮 #}
删除
{% endfor %}
{% import 'macro/pages.html' as pages%}
{{ pages.paginate(tagsPageObj, 'admin.tag_list') }}
{% endblock %}
3.电影管理
3.1 电影增加以及修改的forms表单
from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed
from wtforms import StringField, FileField, TextAreaField, SelectField, DateTimeField, SubmitField, DateField
from wtforms.validators import DataRequired
from app.models import Tag
class BaseForm(FlaskForm):
name = StringField(
label="电影名",
validators=[
DataRequired()
]
)
url = FileField(
label="电影文件",
validators=[
FileAllowed(['mp4', 'avi'], message="文件格式不正确. 只能接收mp4和avi格式")
]
)
info = TextAreaField(
label="电影简介"
)
logo = FileField(
label="电影封面",
validators=[
FileAllowed(['png', 'jpg'], message="文件格式不正确.")
]
)
star = SelectField(
label="电影星级",
coerce=int,
choices=[(i+1, "%s星" %(i+1)) for i in range(5)]
)
tag_id = SelectField(
label="电影标签",
coerce=int,
# choices=[(tag.id, tag.name) for tag in Tag.query.all()]
)
area = StringField(
label="上映地区"
)
length = StringField(
label="电影时长"
)
release_time = DateField(
label="上映时间"
)
def __init__(self, *args, **kwargs):
super(BaseForm, self).__init__(*args, **kwargs)
# 当每次实例化表单时, 都重新查询标签的内容,
self.tag_id.choices = [(tag.id, tag.name) for tag in Tag.query.all()]
class MovieForm(BaseForm):
submit = SubmitField(
label="添加电影"
)
class EditMovieForm(BaseForm):
submit = SubmitField(
label="编辑电影"
)
3.2 电影管理的视图函数
import os
from werkzeug.utils import secure_filename
from app import app, db
from flask import render_template, flash, redirect, url_for,request
from app.admin import admin
from app.admin.forms.movie import MovieForm
from app.admin.utils import write_adminlog, is_admin_login, permission_control
from app.home import change_filename
from app.models import Movie
@admin.route('/movie/list/')
@admin.route('/movie/list//')
@is_admin_login
@permission_control
def movie_list(page=1):
moviesPageObj = Movie.query.paginate(page, per_page=app.config['PER_PAGE'])
return render_template('admin/movie/list.html',
moviesPageObj=moviesPageObj,
app=app)
@admin.route('/movie/add/', methods=['POST', 'GET'])
@is_admin_login
@permission_control
def movie_add():
form = MovieForm()
if form.validate_on_submit():
# ****难点: 电影文件和电影封面要保存到服务器的static/upload目录中;
# 1). 获取上传文件的名称
url = form.url.data.filename
logo = form.logo.data.filename
# 2). 获取文件保存的路径
file_save_path = app.config['MOVIE_UP_DIR']
if not os.path.exists(file_save_path):
os.makedirs(file_save_path)
# 3). 对于上传的文件进行重命名
from app.home import change_filename
url = change_filename(url)
logo = change_filename(logo)
# 4). 保存文件到本地
form.url.data.save(os.path.join(file_save_path, url))
form.logo.data.save(os.path.join(file_save_path, logo))
movie = Movie(
name = form.name.data,
url = url, # 只存储文件的名称
info = form.info.data,
logo=logo,
star=form.star.data,
tag_id=form.tag_id.data,
area=form.area.data,
length = form.length.data,
release_time=form.release_time.data
)
db.session.add(movie)
db.session.commit()
flash("添加电影%s成功" %(form.name.data))
from app.admin.utils import write_adminlog
write_adminlog("添加电影%s成功" %(form.name.data))
return redirect(url_for('admin.movie_add'))
return render_template('admin/movie/add.html',
form=form,
)
@admin.route('/movie/edit//', methods=['GET', 'POST'])
@is_admin_login
@permission_control
def movie_edit(id):
movie = Movie.query.get_or_404(id)
# 给表单赋初始值,文件表单不处理
form = MovieForm(
name=movie.name,
# url=movie.url, # 上传文件,这样赋初始值无效,在前端可以通过上传路径+movie.url来获取文件的保存路径,显示在页面上
info=movie.info,
# logo=movie.logo, # 上传图片和文件类似
star=movie.star,
tag_id=movie.tag_id,
area=movie.area,
release_time=movie.release_time,
length=movie.length,
)
# 对于修改数据,电影文件和封面图已存在,可以非必填:
# 按照教程上测试了validators参数,但始终不行,
# 最终修改required的值就可以了
form.url.validators = []
form.logo.validators = [] # 验证列表为空
if form.validate_on_submit():
data = form.data
# 提交的片名在数据库中已存在,且不是当前的电影名称
if Movie.query.filter_by(name=data['name']).count() == 1 and movie.name != data['name']:
flash('电影片名已存在,请检查', category='err')
return redirect(url_for('admin.movie_edit', edit_id=id))
# 以下和直接修改的数据
movie.name = data['name']
movie.info = data['info']
movie.star = data['star']
movie.tag_id = data['tag_id']
movie.area = data['area']
movie.release_time = data['release_time']
movie.length = data['length']
# 文件保存路径操作
file_save_path = app.config['MOVIE_UP_DIR'] # 文件上传保存路径
if not os.path.exists(file_save_path):
os.makedirs(file_save_path) # 如果文件保存路径不存在,则创建一个多级目录
# 处理电影文件逻辑:先从磁盘中删除旧文件,然后保存新文件
if form.url.data: # 上传文件不为空,才进行保存
# 删除以前的文件
if os.path.exists(os.path.join(file_save_path, movie.url)):
os.remove(os.path.join(file_save_path, movie.url))
# 获取上传文件的名称
file_url = secure_filename(form.url.data.filename)
# 对上传的文件进行重命名
movie.url = change_filename(file_url)
# 保存文件,需要给文件的保存路径+文件名
form.url.data.save(file_save_path + movie.url)
# 处理封面图
if form.logo.data:
if os.path.exists(os.path.join(file_save_path, movie.logo)):
os.remove(os.path.join(file_save_path, movie.logo))
file_logo = secure_filename(form.logo.data.filename)
movie.logo = change_filename(file_logo)
form.logo.data.save(file_save_path + movie.logo)
# 保存到数据库中;
db.session.add(movie)
db.session.commit()
flash('修改电影%s成功' % (movie.name), 'ok')
write_adminlog('修改电影%s成功' % (movie.name))
return redirect(url_for('admin.movie_edit', id=id))
return render_template('admin/movie/edit.html',
form=form,
movie=movie)
@admin.route('/movie/delete//')
@is_admin_login
@permission_control
def movie_del(id=None):
if id:
movie = Movie.query.filter_by(id=id).first_or_404()
# 删除电影同时要从磁盘中删除电影的文件和封面文件
file_save_path = app.config['MOVIE_UP_DIR'] # 文件上传保存路径
# 如果存在将进行删除,不判断,如果文件不存在,删除会报错
if os.path.exists(os.path.join(file_save_path, movie.url)):
os.remove(os.path.join(file_save_path, movie.url))
if os.path.exists(os.path.join(file_save_path, movie.logo)):
os.remove(os.path.join(file_save_path, movie.logo))
# 删除数据库,提交修改,注意后面要把与电影有关的评论都要删除
db.session.delete(movie)
db.session.commit()
# 删除后闪现消息
flash('删除电影%s成功!' % (movie.name), category='ok')
write_adminlog('删除电影%s成功!' % (movie.name))
return redirect(url_for('admin.movie_list', page=1))
3.3 电影管理的页面实现:添加页面以及查看页面
## 添加页面
{% extends 'admin/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}添加电影{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微电影管理系统
首页
电影管理
添加电影
电影列表
{# 面板 #}
添加电影
{{ wtf.quick_form(form) }}
{% endblock %}
## 编辑页面
{% extends 'admin/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}编辑电影{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微电影管理系统
首页
电影管理
编辑电影
电影列表
{# 面板 #}
编辑电影
{{ wtf.quick_form(form) }}
{% endblock %}
## 查看页面
{% extends 'admin/base.html' %}
{% block title %}电影列表{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微电影管理系统
首页
电影管理
添加电影
电影列表
电影列表
{# 登录日志表格#}
编号
片名
电影封面
片长
标签
地区
星级
播放数量
评论数量
上映时间
操作事项
{% for movie in moviesPageObj.items %}
{{ movie.id }}
{{ movie.name }}
{{ movie.length }} 分钟
{{ movie.tag.name }}
{{ movie.area }}
{{ movie.star }} 星
{{ movie.comment_num }}
{{ movie.play_num }}
{{ movie.release_time }}
编辑
删除
{% endfor %}
{% import 'macro/pages.html' as pages %}
{{ pages.paginate(moviesPageObj, 'admin.movie_list') }}
{% endblock %}
4.预告管理
4.1预告管理的forms表单
from flask_wtf import FlaskForm
from wtforms import StringField, FileField, SubmitField
from wtforms.validators import DataRequired
class BaseForm(FlaskForm):
name = StringField(
label='预告标题',
validators=[
DataRequired('请输入预告标题!')
],
)
logo = FileField(
label='预告封面',
validators=[
DataRequired('请上传预告封面!')
],
)
class PreviewForm(BaseForm):
submit = SubmitField(
label='添加预告',
)
class EditPreviewForm(BaseForm):
submit = SubmitField(
label='编辑预告',
)
4.2电影预告的视图函数
import os
from werkzeug.utils import secure_filename
from app import app, db
from flask import render_template, flash, redirect, url_for, request
from app.admin import admin
from app.admin.forms.movie import MovieForm
from app.admin.forms.preview import PreviewForm
from app.admin.utils import write_adminlog, is_admin_login, permission_control
from app.home import change_filename
from app.models import Preview
@admin.route('/preview/add/', methods=['POST', 'GET'])
@is_admin_login
@permission_control
def preview_add():
form = PreviewForm()
if form.validate_on_submit():
data = form.data
# 判断预告标题是否已经存在?
if Preview.query.filter_by(name=data['name']).count() == 1:
flash('预告标题已存在,请检查!', category='err')
return redirect(url_for('admin.preview_add'))
# 存储预告封面;
file_logo = secure_filename(form.logo.data.filename) # 获取上传文件名字
file_save_path = app.config['PREVIEW_UP_DIR'] # 文件上传保存路径
if not os.path.exists(file_save_path):
os.makedirs(file_save_path) # 如果文件保存路径不存在,则创建一个多级目录
logo = change_filename(file_logo) # 文件重命名
form.logo.data.save(os.path.join(file_save_path ,logo)) # 保存文件到磁盘中
# 写入数据库;
preview = Preview(
name=data['name'],
logo=logo # 只在数据库中保存文件名
)
db.session.add(preview)
db.session.commit()
flash('添加预告%s成功' % (preview.name), 'ok')
write_adminlog('添加预告%s成功' % (preview.name))
return redirect(url_for('admin.preview_add'))
return render_template('admin/preview/add.html', form=form)
@admin.route('/preview/list/')
@admin.route('/preview/list//')
@is_admin_login
@permission_control
def preview_list(page=1):
previewsPageObj = Preview.query.paginate(page=page, per_page=app.config['PER_PAGE'])
return render_template('admin/preview/list.html', previewsPageObj=previewsPageObj, app=app)
@admin.route('/preview/delete//')
@is_admin_login
@permission_control
def preview_del(id=None):
if id:
preview = Preview.query.filter_by(id=id).first_or_404()
# 删除电影同时要从磁盘中删除电影的文件和封面文件
file_save_path = app.config['PREVIEW_UP_DIR'] # 文件上传保存路径
# 如果存在将进行删除,不判断,如果文件不存在,删除会报错
if os.path.exists(os.path.join(file_save_path, preview.logo)):
os.remove(os.path.join(file_save_path, preview.logo))
# 删除数据库,提交修改,注意后面要把与电影有关的评论都要删除
db.session.delete(preview)
db.session.commit()
# 删除后闪现消息
flash('删除预告%s成功!' % (preview.name), category='ok')
write_adminlog('删除预告%s成功!' % (preview.name))
return redirect(url_for('admin.preview_list', page=1))
@admin.route('/preview/edit//', methods=['POST', 'GET'])
@is_admin_login
@permission_control
def preview_edit(id=None):
preview = Preview.query.get_or_404(id)
form = PreviewForm(
name=preview.name,
)
# 不验证上传文件
form.logo.validators = []
if form.validate_on_submit():
data = form.data
if Preview.query.filter_by(name=data['name']).count() == 1 and preview.title != data['title']:
flash('预告标题已存在,请重新输入', category='err')
return redirect(url_for('admin.preview_edit', id=id))
preview.name = data['name']
print(data['logo'], type(data['logo']), form.logo.data, type(form.logo.data))
#
#
# 上面两种方式结果一样
# 文件保存路径操作
file_save_path = app.config['PREVIEW_UP_DIR'] # 文件上传保存路径
if not os.path.exists(file_save_path):
os.makedirs(file_save_path) # 如果文件保存路径不存在,则创建一个多级目录
if form.logo.data: # 当有上传新的图片
if os.path.exists(os.path.join(file_save_path, preview.logo)):
os.remove(os.path.join(file_save_path, preview.logo)) # 删除旧图片
file_logo_name = form.logo.data.filename
preview.logo = change_filename(file_logo_name) # 得到新的文件名,保存到输入局
form.logo.data.save(file_save_path + preview.logo)
db.session.commit()
flash('预告%s信息修改成功' % (preview.name), category='ok')
write_adminlog('预告%s信息修改成功' % (preview.name))
return redirect(url_for('admin.preview_edit', id=id))
return render_template('admin/preview/edit.html', form=form, preview=preview)
4.3 电影预告的页面实现
## 添加预告
{% extends 'admin/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}添加预告{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微预告管理系统
首页
预告管理
添加预告
预告列表
{# 面板 #}
添加预告
{{ wtf.quick_form(form) }}
{% endblock %}
## 编辑预告
{% extends 'admin/base.html' %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}编辑预告{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微预告管理系统
首页
预告管理
编辑预告
预告列表
{# 面板 #}
编辑预告
{{ wtf.quick_form(form) }}
{% endblock %}
## 预告列表
{% extends 'admin/base.html' %}
{% block title %}预告列表{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微预告管理系统
首页
预告管理
添加预告
预告列表
预告列表
{# 登录日志表格#}
编号
预告名称
预告封面
添加时间
操作事项
{% for preview in previewsPageObj.items %}
{{ preview.id }}
{{ preview.name }}
{{ preview.addtime }}
编辑
删除
{% endfor %}
{% endblock %}
5.会员管理
5.1 会员管理是查看前台登录的会员信息,所以不用生成表单
5.2 会员管理的视图函数
import os
from werkzeug.utils import secure_filename
from app import app, db
from flask import render_template, flash, redirect, url_for, request
from app.admin import admin
from app.admin.utils import write_adminlog, is_admin_login, permission_control
from app.models import User
@admin.route("/user/list/")
@admin.route("/user/list//")
@is_admin_login
@permission_control
def user_list(page=1):
usersPageObj = User.query.paginate(page=page, per_page=app.config['PER_PAGE'])
return render_template('admin/user/list.html', usersPageObj=usersPageObj, app=app)
@admin.route("/user/view//")
@is_admin_login
@permission_control
def user_view(user_id=None):
if user_id:
user = User.query.get_or_404(user_id)
return render_template('admin/user/view.html',
user=user,
app=app)
@admin.route("/user/delete//")
@is_admin_login
@permission_control
def user_del(id=None):
if id:
user = User.query.get_or_404(id)
# 删除同时要从磁盘中删除封面文件
file_save_path = app.config['FC_DIR'] # 头像上传保存路径
# 如果存在将进行删除,不判断,如果文件不存在删除会报错
if os.path.exists(os.path.join(file_save_path, user.face)):
os.remove(os.path.join(file_save_path, user.face))
# 删除数据库,提交修改
db.session.delete(user)
db.session.commit()
# 删除后闪现消息
flash('删除会员%s成功!' % (user.name), category='ok')
write_adminlog('删除会员%s成功!' % (user.name))
return redirect(url_for('admin.user_list', page=1))
5.3 会员管理的页面实现
## 会员列表的查看
{% extends 'admin/base.html' %}
{% block title %}会员列表{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微电影管理系统
首页
会员管理
{# 会员列表 #}
会员列表
{# 登录日志表格#}
编号
昵称
邮箱
手机
头像
状态
注册时间
操作事项
{% for user in usersPageObj.items %}
{{ user.id }}
{{ user.name }}
{{ user.email }}
{{ user.phone }}
{% if user.face %}
{% else %}
未上传头像
{% endif %}
冻结/正常
{{ user.addtime }}
查看
删除
{% endfor %}
{% endblock %}
## 具体某会员的额详细信息查看
{% extends 'admin/base.html' %}
{% block title %}会员详情页{% endblock %}
{% block content %}
{# 参考 路径导航: https://v3.bootcss.com/components/#breadcrumbs #}
微电影管理系统
首页
会员管理
{# 会员列表 #}
会员详情页
编号:
{{ user.id }}
昵称:
{{ user.name }}
邮箱:
{{ user.email }}
手机:
{{ user.phone }}
头像:
{% if user.face %}
{% else %}
未上传头像
{% endif %}
注册时间:
{{ user.addtime }}
个性简介:
{{ user.info }}
{% endblock %}