基于flask的微电影管理系统——前台管理(1)

1. 需要的css和js以及fonts样式都从网上下载

在这里插入图片描述

2.创建home前台管理的蓝图

home模块包下__init__.py中创建

创建蓝图,到处所有的视图函数

from flask import Blueprint

home=Blueprint('home',__name__)

from app.home.views import *

app下的__init__.py添加蓝图注册,连接各模块

from app.home import home as home_blueprint

# 注册home蓝图, 不添加前缀
app.register_blueprint(home_blueprint)

3.forms.py中编写需要的表单,

from flask_wtf import FlaskForm
from wtforms import SubmitField, StringField, PasswordField, FileField, TextAreaField
from wtforms.validators import DataRequired,Length,EqualTo,Email
from flask_wtf.file import FileAllowed


class BaseForm(FlaskForm):
    username = StringField(
        label="用户名",
        validators=[
            DataRequired()
        ]
    )

    password = PasswordField(
        label="密码",
        validators=[
            DataRequired(),
            Length(6, 12, message="密码长度必须为6-12")

        ]
    )


class LoginForm(BaseForm):
    submit = SubmitField(
        label="登录"
    )

class RegisterForm(BaseForm):
    repassword = PasswordField(
        label="确认密码",
        validators=[
            EqualTo('password', message="两次密码不一致")
        ]
    )
    email = StringField(
        label="邮箱",
        validators=[
            Email(message="邮箱格式不正确")
        ]
    )

    submit = SubmitField(
        label="注册"
    )


class EditUserForm(FlaskForm):
    username = StringField(
        label="用户名",
        validators=[
            DataRequired()

        ]
    )
    email = StringField(
        label="邮箱",
        # validators=[
        #     Email(message="邮箱格式不正确")
        # ]
    )

    phone = StringField(
        label="电话",
        # validators=[
        #     Regexp(r'1\d{10}', message="电话号码格式不正确")
        # ]
    )
    face = FileField(
        label="用户头像",
        validators=[
            # *******限制用户上传文件的格式
            FileAllowed(['png', 'jpg'], message="用户头像格式错误, 必须为png或者jpg")

        ]
    )

    info = TextAreaField(
        label="用户简介",
    )

    submit = SubmitField(
        label="更新信息"
    )



class PwdForm(FlaskForm):
    old_pwd = PasswordField(
        label="旧密码",
        validators=[
            DataRequired()
        ],
    # 设置key-values值
    render_kw = {
        'placeholder' : "请输入旧密码"
    }
    )
    new_pwd = PasswordField(
        label="新密码",
        validators=[
            DataRequired()
        ],
        render_kw={
            'placeholder': "请输入新密码"
        }
    )

    submit = SubmitField(
        label="修改密码"
    )

4.在home包内添加需要用到的装饰器以及函数

from functools import wraps

from flask import session, flash, redirect, url_for


def is_login(f):
    """用来判断用户是否登录成功"""
    @wraps(f)
    def wrapper(*args,**kwargs):
        # 判断session对象中是否有seesion['user'],
        # 如果包含信息, 则登录成功, 可以访问主页;
        # 如果不包含信息, 则未登录成功, 跳转到登录界面;;
        if session.get('user', None):
            return f(*args, **kwargs)
        else:
            flash("用户必须登录才能访问%s" % (f.__name__))
            return redirect(url_for('home.login'))

    return wrapper

def change_filename(filename):
    """在原有文件的基础上添加时间标签"""
    from datetime import  datetime
    return  datetime.now().strftime('%Y%m%d_%H%M%S') + filename

5.视图函数home包下的views.py和templates包内home中的html文件,实现与前台交互

5-1 需要导入的模块包

import os
from flask import render_template, flash, redirect, url_for, session, request
from werkzeug.security import generate_password_hash
from app import app, db
from app.home.forms import RegisterForm, LoginForm, EditUserForm, PwdForm
from app.home.utils import is_login, change_filename
from app.models import Movie, Preview, User, Comment, Userlog, MovieCollect
from . import home

继承用的base.html

{% extends 'bootstrap/base.html' %}

{% block styles %}
    {#  先继承父类的css样式导入   #}
    {{ super() }}
    <link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
{% endblock %}


{% block scripts %}

    {{ super() }}
    {#    实质使导入moment.js库的, 通过Flask-moment集成了起来#}
    {{ moment.include_moment() }}
    <script src="{{ url_for('static', filename='js/echarts.min.js') }}"></script>

{% endblock %}
{% block navbar %}
    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">微电影网站</a>
            </div>

            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">


                <ul class="nav navbar-nav navbar-right">
                    {#       分类讨论:
                            1. 如果没有登录, 显示登录和注册按钮;
                            2. 如果登录成功, 显示用户名称和注销按钮

            #}

                <li><a href="#">电影</a></li>
                    {% if not session.user %}
                        <li><a href="{{ url_for('home.login') }}">登录</a></li>
                        <li><a href="{{ url_for('home.register') }}">注册</a></li>
                    {% else %}
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                               aria-haspopup="true"
                               aria-expanded="false">当前用户:{{ session.user }} <span class="caret"></span></a>
                            <ul class="dropdown-menu">
                                <li role="separator" class="divider"></li>
                                <li><a href="{{ url_for('home.logout') }}">注销</a></li>
                            </ul>
                        </li>

                    {% endif %}
                </ul>


            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>


    {#让每个页面都可以获取闪现信息闪现#}
    {% for item in get_flashed_messages() %}

        <div class="alert alert-warning alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
                    aria-hidden="true">&times;</span></button>
            {{ item }}
        </div>
    {% endfor %}
{% endblock %}

侧边栏的实现 usermneu.html

<div class="col-lg-2">
<div class="list-group">
    <a href="{{ url_for('home.user') }}" class="list-group-item" id="md-1">
        <span class="glyphicon glyphicon-user"></span>&nbsp;会员中心
    </a>
    <a href="{{ url_for('home.pwd') }}" class="list-group-item" id="md-2">
        <span class="glyphicon glyphicon-lock"></span>&nbsp;修改密码
    </a>
    <a href="{{ url_for('home.comments') }}" class="list-group-item" id="md-3">
        <span class="glyphicon glyphicon-comment"></span>&nbsp;评论记录
    </a>
    <a href="{{ url_for('home.userlog') }}" class="list-group-item" id="md-4">
        <span class="glyphicon glyphicon-calendar"></span>&nbsp;登录日志
    </a>
    <a href="{{ url_for('home.moviecollect') }}" class="list-group-item" id="md-5">
        <span class="glyphicon glyphicon-heart"></span>&nbsp;收藏电影
    </a>
</div>
</div>

6-2 主页面视图函数

@home.route('/')
@home.route('/<int:page>/')
def index(page=1):
    # 预告信息
    previews = Preview.query.all()
    # 标签信息
    tags = Tag.query.all()
    # 星级信息[{'num':1, 'info':'1星'}, {'num':2, 'info':'2星'}.........]
    star_list = [{'num': num + 1, 'info': '%s星' % (num + 1)} for num in range(5)]
    # 上映时间信息(只显示近5年的)

    now_year = int(time.localtime().tm_year)
    year_list = [year for year in range(now_year, now_year - 5, -1)]
    # 电影查询
    page_movies = Movie.query
    # 1). 判断用户是否选择标签; GET请求方式;如果为0代表未选择;
    tag_id = int(request.args.get('tag_id', 0))

    if tag_id:
        page_movies = page_movies.filter_by(tag_id=tag_id)

    # 2). 判断用户是否选择星级;GET请求方式;如果为0代表未选择;
    star_num = int(request.args.get('star_num', 0))
    if star_num:
        page_movies = page_movies.filter_by(star=star_num)

    # 3). 判断用户是否选择年份;GET请求方式;如果为1代表所有日期;
    year = int(request.args.get('year', 0))
    print(year)
    if year:
        # 筛选年份
        page_movies = page_movies.filter(extract('year', Movie.release_time) == year)
        print(str(extract('year', Movie.release_time)))

    # 播放数为1----从高到低进行排序;
    # 播放数为0----从低到高进行排序;
    play_num = int(request.args.get('play_num', 1))
    if play_num == 1:
        # 降序
        page_movies = page_movies.order_by(Movie.play_num.desc())
    else:
        # 升序
        page_movies = page_movies.order_by(Movie.play_num.asc())

    comment_num = int(request.args.get('comment_num', 1))  # 1为从高到低,0为从低到好
    if int(comment_num) == 1:
        page_movies = page_movies.order_by(Movie.comment_num.desc())
    else:
        page_movies = page_movies.order_by(Movie.comment_num.asc())

    page_movies = page_movies.paginate(page, per_page=app.config['PER_PAGE'])
    return render_template('home/index.html',
                           previews=previews,
                           tags=tags,
                           star_list=star_list,
                           year_list=year_list,
                           page_movies=page_movies,
                           app=app,
                           )

对应的页面实现的index.html内容

{% extends 'home/base.html' %}
{#
1. 轮播图:http://www.runoob.com/try/try.php?filename=bootstrap3-plugin-carousal-caption
2. 各种选择标签
3. 相关电影: https://v3.bootcss.com/components/#thumbnails-custom-content
#}
{% block title %}首页{% endblock %}
{% block content %}






    <div class="container-fluid">
        <div class="col-lg-10 col-lg-offset-1">
            {#   轮播图   #}
            <div id="myCarousel" class="carousel slide">
                <!-- 轮播(Carousel)指标 -->
                <ol class="carousel-indicators">
                    {% for preview in previews %}
                        {% if loop.first %}
                            <li data-target="#myCarousel" data-slide-to="0" class="active"></li>
                        {% else %}
                            <li data-target="#myCarousel" data-slide-to="{{ loop.index0 }}"></li>
                        {% endif %}
                    {% endfor %}
                </ol>
                <!-- 轮播(Carousel)项目 -->
                <div class="carousel-inner">
                    {#                 #}
                    {% for preview in previews %}

                        {% if loop.first %}
                            <div class="item active">
                                <img src="{{ url_for('static', filename=app.config['PREVIEW_UP_DIR_LAST'] + preview.logo) }}"
                                     alt="First slide">
                                <div class="carousel-caption">{{ preview.name }}</div>
                            </div>
                        {% else %}
                            <div class="item">
                                <img src="{{ url_for('static', filename=app.config['PREVIEW_UP_DIR_LAST'] + preview.logo) }}"
                                     alt="Second slide">
                                <div class="carousel-caption">{{ preview.name }}</div>
                            </div>
                        {% endif %}
                    {% endfor %}

                </div>
                <!-- 轮播(Carousel)导航 -->
                <a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
                    <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
                    <span class="sr-only">Previous</span>
                </a>
                <a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
                    <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
                    <span class="sr-only">Next</span>
                </a>
            </div>

            {#    各种选择标签   #}
            <table class="table text-left table-bordered" id="movietags">
                <tr>
                    <td style="width:10%;">电影标签</td>
                    <td style="width:80%;">
                        {% for tag in tags %}
                            <a class="label label-info" href="{{ url_for('home.index',page=1) }}?tag_id={{ tag.id }}">
                                <span class="glyphicon glyphicon-tag"></span>&nbsp;{{ tag.name }}</a>
                        {% endfor %}
                </tr>
                <tr>
                    <td>电影星级</td>
                    <td>
                        {% for star in star_list %}
                            <a class="label label-warning"
                               href="{{ url_for('home.index',page=1) }}?star_num={{ star.num }}">
                                <span class="glyphicon glyphicon-star"></span>&nbsp;&nbsp;{{ star.info }}</a>
                        {% endfor %}
                        &nbsp;
                    </td>
                </tr>
                <tr>
                    <td>上映时间</td>
                    <td>
                        {% for year in year_list %}&nbsp;
                            <a class="label label-default"
                               href="{{ url_for('home.index',page=1) }}?year={{ year }}">
                                <span class="glyphicon glyphicon-time"></span>&nbsp{{ year }}</a>
                        {% endfor %}
                    </td>
                </tr>
                <tr>
                    <td>播放数量</td>
                    <td>
                        <a class="label label-success"
                           href="{{ url_for('home.index',page=1) }}?play_num=1"
                        ><span
                                class="glyphicon glyphicon-arrow-down"></span>&nbsp;从高到底</a>
                        &nbsp;
                        <a class="label label-danger"
                           href="{{ url_for('home.index',page=1) }}?play_num=0"><span
                                class="glyphicon glyphicon-arrow-up"></span>&nbsp;从低到高</a>
                    </td>
                </tr>
                <tr>
                    <td>评论数量</td>
                    <td>
                        <a class="label label-success"
                           href="{{ url_for('home.index',page=1) }}?comment_num=1"
                        ><span
                                class="glyphicon glyphicon-arrow-down"></span>&nbsp;从高到底</a>
                        &nbsp;
                        <a class="label label-danger"
                           href="{{ url_for('home.index',page=1) }}?comment_num=0"
                        ><span
                                class="glyphicon glyphicon-arrow-up"></span>&nbsp;从低到高</a>
                    </td>
                </tr>
            </table>


            {#  电影列表信息           #}

            <div class="row">
                {% for movie in page_movies.items %}
                    <div class="col-sm-3 col-md-3">
                        <div class="thumbnail">
                            <img src="{{ url_for('static', filename=app.config['MOVIE_UP_DIR_LAST'] + movie.logo) }}"
                                 alt="..." style="width: 240px; height: 330px">
                            <div class="caption">
                                <h3>{{ movie.name }}</h3>
                                <p>
                                    {{ movie.info }}
                                </p>

                                <div>
                                    {% for star in range(movie.star) %}
                                        <span class="glyphicon glyphicon-star" style="color:#FFD119"></span>
                                    {% endfor %}
                                    {% for emptystar in range(5-movie.star) %}
                                        <span class="glyphicon glyphicon-star-empty" style="color:#FFD119"></span>
                                    {% endfor %}
                                </div>

                                <a href="{{ url_for('home.play', id=movie.id) }}" class="btn btn-success btn-block"
                                   target="_blank" role="button">
                                    <span class="glyphicon glyphicon-play"></span>&nbsp;播放</a>
                            </div>
                        </div>


                    </div>
                {% endfor %}
            </div>

            {#            分页显示  #}
            <div class="col-md-12 text-center">
                <nav aria-label="Page navigation">
                    <ul class="pagination">
                        <li>
                            <a href="#" aria-label="First">
                                <span aria-hidden="true">首页</span>
                            </a>
                        </li>
                        <li>
                            <a href="#" aria-label="Previous">
                                <span aria-hidden="true">上一页</span>
                            </a>
                        </li>
                        <li><a href="#">1&nbsp;/&nbsp;10</a></li>
                        <li>
                            <a href="#" aria-label="Next">
                                <span aria-hidden="true">下一页</span>
                            </a>
                        </li>
                        <li>
                            <a href="#" aria-label="Last">
                                <span aria-hidden="true">尾页</span>
                            </a>
                        </li>
                    </ul>
                </nav>
            </div>


        </div>

    </div>

{% endblock %}

在这里插入图片描述

6-3 注册页面的视图函数

@home.route('/register/',methods=['GET','POST'])
def register():
    form=RegisterForm()
    if form.validate_on_submit():
        # 1. 从前端获取用户输入的值;
        email = form.email.data
        username = form.username.data
        password = form.password.data

        # 2. 判断用户是否已经存在? 如果返回位None,说明可以注册;
        u = User.query.filter_by(name=username).first()
        if u:
            flash("用户%s已经存在" % (u.name))
            return redirect(url_for('home.register'))
        else:
            u = User(name=username, email=email)
            u.password = generate_password_hash(password)  # 对于密码进行加密
            db.session.add(u)
            db.session.commit()
            flash("注册用户%s成功" % (u.name))
            return redirect(url_for('home.login'))
    return render_template('home/register.html',
                           form=form)

对应的页面实现的register.html内容

{% extends 'home/base.html' %}
{% import 'bootstrap/wtf.html'  as wtf %}


{% block title %}
    注册
{% endblock %}



{% block content %}
    <div class="container">
        <div class="col-lg-8 col-lg-offset-2">


            <div class="panel panel-success">
                <div class="panel-heading">
                    <h1 class="panel-title"><span class="glyphicon glyphicon-log-in">

                    </span>&nbsp;&nbsp;注册</h1>
                </div>
                <div class="panel-body">
                    {{ wtf.quick_form(form) }}
                </div>
            </div>

        </div>


    </div>

{% endblock %}

在这里插入图片描述

6-4 登录页面的视图函数

@home.route('/login/', methods=['POST', 'GET'])
def login():
    from app.models import User, Userlog
    form = LoginForm()
    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        user = User.query.filter_by(name=username).first()
        # 使用user.verify_password方法验证密码,
        # 因为相同密码每一次generate_password_hash加密后都不一样
        if user and user.verify_password(password):
            # session信息的保存
            session['user_id'] = user.id
            session['user'] = user.name
            flash("用户%s登录成功" % (user.name))
            remote_ip = request.remote_addr
            # 将登录信息写到日志中;
            userlog = Userlog(user_id=user.id,
                              ip=remote_ip,
                              area='内网IP')
            db.session.add(userlog)
            db.session.commit()

            # 从index蓝图里面寻找index函数;
            return redirect(url_for('home.user'))
        else:
            flash("用户登录失败")
            return redirect(url_for('home.login'))
    return render_template('home/login.html',
                           form=form)

实现页面显示的login.html

{% extends 'home/base.html' %}
{% import 'bootstrap/wtf.html'  as wtf %}


{% block title %}
    登录
{% endblock %}



{% block content %}
    <div class="container">
        <div class="col-lg-8 col-lg-offset-2">


            <div class="panel panel-success">
                <div class="panel-heading">
                    <h1 class="panel-title"><span class="glyphicon glyphicon-log-in">

                    </span>&nbsp;&nbsp;登录</h1>
                </div>
                <div class="panel-body">
                    {{ wtf.quick_form(form) }}
                </div>
            </div>

        </div>


    </div>

{% endblock %}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/GLH_2236504154/article/details/88899210
今日推荐