1.使用虚拟环境Virtualenv来创建项目
2. Flask框架介绍
Flask框架是一个用Python编写的轻量级Web应用程序框架,依赖于Werkzeug和Jinja2两个外部库。Werkzeug是一个WSGI工具包,用于接收和处理HTTP请求,匹配视图函数,支持Cookie和会话管理,交互式调试等功能。Jinja2是一个模板引擎,用于将响应结果渲染到模板文件,支持动态网页的呈现。Flask框架的核心构成简单,但具有很强的扩展性和兼容性,可以根据需要选择不同的数据库和其他功能扩展。Flask框架主要用于开发Web应用程序,例如网站或Web服务。
安装flask框架,使用以下代码,或者直接在pycharm设置的++下安装
pip install flask
3.创建Flask项目
在终端中进入要创建项目的目录,输入以下命令创建Flask项目:
mkdir Online-Music-main
cd Online-Music-main
4. 创建Flask app
在Online-Music-main目录下创建一个Python文件,命名为app.py
# _*_ codding:utf-8 _*_
from app import create_app, db
from app.models import *
from flask_script import Manager, Shell
from flask_migrate import Migrate, MigrateCommand
from flask import render_template
app = create_app('default')
manager = Manager(app)
migrate = Migrate(app, db)
def make_shell_context():
return dict(app=app, db=db)
manager.add_command("shell", Shell(make_context=make_shell_context))
manager.add_command('db', MigrateCommand)
@app.errorhandler(404)
def page_not_found(error):
"""
404
"""
return render_template("home/404.html"), 404
if __name__ == '__main__':
manager.run()
5.配置config.py文件,连接数据库
# -*- coding=utf-8 -*-
import os
class Config:
SECRET_KEY = 'mrsoft'
SQLALCHEMY_TRACK_MODIFICATIONS = True
@staticmethod
def init_app(app):
'''初始化配置文件'''
pass
# the config for development
class DevelopmentConfig(Config):
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@127.0.0.1:3306/music'
DEBUG = True
# define the config
config = {
'default': DevelopmentConfig
}
6在添加models模型,
from . import db
# 用户表
class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True) # 编号
username = db.Column(db.String(100)) # 用户名
pwd = db.Column(db.String(100)) # 密码
flag = db.Column(db.Boolean,default=0) # 用户标识,0:普通用户 1:管理员
def __repr__(self):
return '<User %r>' % self.name
def check_pwd(self, pwd):
"""
检测密码是否正确
:param pwd: 密码
:return: 返回布尔值
"""
return self.pwd == pwd
# 歌手表
class Artist(db.Model):
__tablename__ = 'artist'
id = db.Column(db.Integer, primary_key=True) # 编号
artistName = db.Column(db.String(100)) # 歌手名
style = db.Column(db.Integer) # 歌手类型
imgURL = db.Column(db.String(100)) # 头像
isHot = db.Column(db.Boolean,default=0) # 是否热门
# 歌曲表
class Song(db.Model):
__tablename__ = 'song'
id = db.Column(db.Integer, primary_key=True) # 编号
songName = db.Column(db.String(100)) # 歌曲名称
singer = db.Column(db.String(100)) # 歌手名称
fileURL = db.Column(db.String(100)) # 歌曲图片
hits = db.Column(db.Integer,default=0) # 点击量
style = db.Column(db.Integer) # 歌曲类型 0:全部 1:华语 2:欧美 3:日语 4:韩语 5 其他
collect = db.relationship('Collect', backref='song') # 收藏外键关系关联
# 歌曲收藏
class Collect(db.Model):
__tablename__ = "collect"
id = db.Column(db.Integer, primary_key=True) # 编号
song_id = db.Column(db.Integer, db.ForeignKey('song.id')) # 所属歌曲
user_id = db.Column(db.Integer) # 所属用户
7.写视图views.py,最后渲染前端网页实现界面
# _*_ coding: utf-8 _*_
from . import home
from app import db
from app.home.forms import LoginForm,RegisterForm,SuggetionForm
from app.models import User ,Artist,Song,Collect
from flask import render_template, url_for, redirect, flash, session, request,jsonify
from werkzeug.security import generate_password_hash
from functools import wraps
def admin_login(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if session['username'] != 'mr' :
return redirect(url_for("home.index"))
return f(*args, **kwargs)
return decorated_function
def user_login(f):
"""
登录装饰器
"""
@wraps(f)
def decorated_function(*args, **kwargs):
if "user_id" not in session:
return "<script>alert('请先登录');history.go(-1)</script>"
return f(*args, **kwargs)
return decorated_function
@home.route("/contentFrame")
def contentFrame():
"""
主页面
"""
hot_artist = Artist.query.filter_by(isHot=1).limit(12).all() # 获取歌手数据
hot_song = Song.query.order_by(Song.hits.desc()).limit(10).all() # 获取歌曲数据
return render_template('home/contentFrame.html',hot_artist=hot_artist,hot_song=hot_song) # 渲染模板
@home.route("/")
def index():
"""
首页
"""
return render_template('home/index.html') # 渲染模板
@home.route("/login/", methods=["GET", "POST"])
def login():
"""
登录
"""
if request.method == 'POST':
username = request.form.get("username")
pwd = request.form.get("pwd")
user = User.query.filter_by(username=username).first() # 获取用户信息
res = {}
# 检测用户名
if not user :
res['status'] = -1
res['message'] = '用户名不存在'
return jsonify(res)
# 检测密码
if not user.check_pwd(pwd): # 调用check_pwd()方法,检测用户名密码是否匹配
res['status'] = -2
res['message'] = '用户名和密码不匹配'
return jsonify(res)
# 用户名和密码正确,写入session
session["user_id"] = user.id # 将user_id写入session, 后面用户判断用户是否登录
session["username"] = user.username # 将user_id写入session, 后面用户判断用户是否登录
res['status'] = 1
res['message'] = '登录成功'
return jsonify(res)
return render_template("home/login.html")
@home.route("/register/", methods=["GET","POST"])
def register():
"""
注册功能
"""
if request.method == "POST": # 提交注册表单
username = request.form.get("username")
pwd = request.form.get("pwd")
# 判断用户名是否存在
user = User.query.filter_by(username=username).first() # 获取用户信息
if user:
res = {}
res['status'] = -2
res['message'] = '该用户已存在'
return jsonify(res)
# 写入到user表
try:
# 为User类属性赋值
user = User(
username = username, # 用户名
pwd = generate_password_hash(pwd),# 对密码加密
)
db.session.add(user) # 添加数据
db.session.commit() # 提交数据
res = {}
res['status'] = 1
res['message'] = '注册成功'
except:
res = {}
res['status'] = -1
res['message'] = '注册失败'
return jsonify(res)
return render_template("home/register.html")
@home.route("/logout/")
def logout():
"""
退出登录
"""
# 重定向到home模块下的登录。
session.pop("user_id", None)
session.pop("username", None)
return redirect(url_for('home.index'))
@home.route("/artist/<int:id>")
def artist(id=None):
"""
歌手页
"""
song = Song.query.join(Artist,Song.singer==Artist.artistName).filter(Artist.id==id).all()
hot_artist = Artist.query.limit(6).all()
return render_template('home/artist.html',song=song,hot_artist=hot_artist) # 渲染模板
@home.route("/toplist")
def toplist():
top_song = Song.query.order_by(Song.hits.desc()).limit(30).all()
hot_artist = Artist.query.limit(6).all()
return render_template('home/toplist.html', top_song=top_song, hot_artist=hot_artist) # 渲染模板
@home.route('/style_list')
def styleList():
"""
曲风
"""
type = request.args.get('type',0,type=int)
page = request.args.get('page',type=int) # 获取page参数值
if type:
page_data = Song.query.filter_by(style=type).order_by(Song.hits.desc()).paginate(page=page, per_page=10)
else:
page_data = Song.query.order_by(Song.hits.desc()).paginate(page=page, per_page=10)
return render_template('home/styleList.html', page_data=page_data,type=type) # 渲染模板
@home.route('/artist_list')
def artistList():
'''
歌手列表
'''
type = request.args.get('type',0,type=int)
page = request.args.get('page',type=int) # 获取page参数值
if type:
page_data = Artist.query.filter_by(style=type).paginate(page=page, per_page=10)
else:
page_data = Artist.query.paginate(page=page, per_page=10)
return render_template('home/artistList.html', page_data=page_data,type=type) # 渲染模板
# 发现音乐
@home.route('/search')
def search():
keyword = request.args.get('keyword') # 获取关键字
page = request.args.get('page', type=int) # 获取page参数值
if keyword:
keyword = keyword.strip()
page_data = Song.query.filter(Song.songName.like('%'+keyword+'%')).order_by(Song.hits.desc()).paginate(page=page, per_page=10)
else:
page_data = Song.query.order_by(Song.hits.desc()).paginate(page=page, per_page=10)
return render_template('home/search.html',keyword=keyword,page_data=page_data)
@home.route('/modify_password',methods=['GET','POST'])
def modifyPassword():
if request.method == 'POST':
old_pwd = request.form.get("old_pwd")
new_pwd = request.form.get("new_pwd")
# 检查原始密码是否正确
user = User.query.filter_by(id=session['user_id']).first() # 获取用户信息
res = {}
if not user.check_pwd(old_pwd):
res['status'] = -1
res['message'] = '原始密码错误'
return jsonify(res)
# 更改密码
try:
user.pwd = generate_password_hash(new_pwd) # 对新密码加密
db.session.add(user)
db.session.commit()
res['status'] = 1
res['message'] = '密码修改成功'
return jsonify(res)
except:
res['status'] = -2
res['message'] = '密码修改错误'
return jsonify(res)
return render_template("home/modifyPassword.html")
@home.route("/collect")
@user_login
def collect():
"""
收藏歌曲
"""
song_id = request.args.get("id", "") # 接收传递的参数歌曲ID
user_id = session['user_id'] # 获取当前用户的ID
collect = Collect.query.filter_by( # 根据用户ID和景区ID判断是否该收藏
user_id =int(user_id),
song_id=int(song_id)
).count()
res = {}
# 已收藏
if collect == 1:
res['status'] = 0
res['message'] = '已经收藏'
# 未收藏进行收藏
if collect == 0:
collect = Collect(
user_id =int(user_id),
song_id=int(song_id)
)
db.session.add(collect) # 添加数据
db.session.commit() # 提交数据
res['status'] = 1
res['message'] = '收藏成功'
return jsonify(res) # 返回json数据
@home.route("/collect_list")
@user_login
def collectList():
page = request.args.get('page',type=int) # 获取page参数值
page_data = Collect.query.paginate(page=page, per_page=10)
return render_template('home/collectList.html',page_data=page_data)
@home.route("/manage_artist_list")
@admin_login
def manageArtist():
'''
后台管理
'''
page = request.args.get('page',type=int) # 获取page参数值
page_data = Artist.query.paginate(page=page, per_page=10)
return render_template('home/manageArtist.html', page_data=page_data)
@home.route("/manage_artist_add", methods=["GET","POST"])
@admin_login
def manageArtistAdd():
'''
新增歌手
'''
if request.method == "POST": # 提交注册表单
artistName = request.form.get("artistName")
style = request.form.get("style")
imgURL = request.form.get("imgURL")
isHot = request.form.get("isHot")
# 判断歌手是否存在
artist = Artist.query.filter_by(artistName=artistName).first() # 获取用户信息
if artist:
res = {}
res['status'] = -2
res['message'] = '该歌手已存在'
return jsonify(res)
# 写入到Artist表
try:
# 为Artist类属性赋值
artist = Artist(
artistName = artistName,
style = int(style),
imgURL = imgURL,
isHot = int(isHot)
)
db.session.add(artist) # 添加数据
db.session.commit() # 提交数据
res = {}
res['status'] = 1
res['message'] = '添加成功'
except:
res = {}
res['status'] = -1
res['message'] = '添加失败'
return jsonify(res)
return render_template('home/manageArtistAdd.html')
@home.route("/manage_artist_edit", methods=["GET","POST"])
@admin_login
def manageArtistEdit():
'''
编辑歌手
'''
id = request.values['id'] # POST和GET提交都可以获取ID
artist = Artist.query.filter_by(id=id).first() # 获取用户信息
if request.method == "POST": # 提交注册表单
# 更改Artist表
artistName = request.form.get("artistName")
style = request.form.get("style")
imgURL = request.form.get("imgURL")
isHot = request.form.get("isHot")
try:
artist.artistName = artistName
artist.style = int(style)
artist.imgURL = imgURL
artist.isHot = int(isHot)
db.session.add(artist) # 添加数据
db.session.commit() # 提交数据
res = {}
res['status'] = 1
res['message'] = '保存成功'
except :
res = {}
res['status'] = -1
res['message'] = '保存失败'
return jsonify(res)
return render_template('home/manageArtistEdit.html',artist=artist)
@home.route("/manage_artist_del")
@admin_login
def manageArtistDel():
'''
删除歌手
'''
id = request.args.get('id') # 获取ID
try:
artist = Artist.query.get_or_404(int(id))
db.session.delete(artist)
db.session.commit()
res = {}
res['status'] = 1
res['message'] = '删除成功'
except:
res = {}
res['status'] = -1
res['message'] = '删除失败'
return jsonify(res)
@home.route("/manage_song_list")
@admin_login
def manageSong():
'''
歌曲管理
'''
page = request.args.get('page',type=int) # 获取page参数值
page_data = Song.query.paginate(page=page, per_page=10)
return render_template('home/manageSong.html', page_data=page_data)
@home.route("/manage_song_add", methods=["GET","POST"])
@admin_login
def manageSongAdd():
'''
新增歌曲
'''
if request.method == "POST": # 提交注册表单
songName = request.form.get("songName")
singer = request.form.get("singer")
style = request.form.get("style")
fileURL = request.form.get("fileURL")
# 判断歌手是否存在
song = Song.query.filter_by(songName=songName).first() # 获取歌曲信息
if song:
res = {}
res['status'] = -2
res['message'] = '该歌曲已存在'
return jsonify(res)
# 写入到Song表
# 为Song类属性赋值
try:
# 为Song类属性赋值
song = Song(
songName = songName, # 歌曲名称
singer = singer, # 歌手
style = 1, # 歌曲类型
fileURL = fileURL # 文件路径
)
db.session.add(song) # 添加数据
db.session.commit() # 提交数据
res = {}
res['status'] = 1
res['message'] = '添加成功'
except :
res = {}
res['status'] = -1
res['message'] = '添加失败'
return jsonify(res)
return render_template('home/manageSongAdd.html')
@home.route("/manage_song_edit", methods=["GET","POST"])
@admin_login
def manageSongEdit():
'''
编辑歌曲
'''
id = request.values['id'] # POST和GET提交都可以获取ID
song = Song.query.filter_by(id=id).first() # 获取用户信息
if request.method == "POST": # 提交注册表单
# 更改Song表
songName = request.form.get("songName")
singer = request.form.get("singer")
style = request.form.get("style")
fileURL = request.form.get("fileURL")
try:
song.songName = songName
song.singer = singer
song.style = int(style)
song.fileURL = fileURL
db.session.add(song) # 添加数据
db.session.commit() # 提交数据
res = {}
res['status'] = 1
res['message'] = '保存成功'
except :
res = {}
res['status'] = -1
res['message'] = '保存失败'
return jsonify(res)
return render_template('home/manageSongEdit.html',song=song)
@home.route("/manage_song_del")
@admin_login
def manageSongDel():
'''
删除歌曲
'''
id = request.args.get('id') # 获取ID
try:
song = Song.query.get_or_404(int(id))
db.session.delete(song)
db.session.commit()
res = {}
res['status'] = 1
res['message'] = '删除成功'
except:
res = {}
res['status'] = -1
res['message'] = '删除失败'
return jsonify(res)
@home.route('/addHit')
def addHit():
'''
点击量加1
'''
id = request.args.get('id')
song = Song.query.get_or_404(int(id))
if not song:
res = {}
res['status'] = -1
res['message'] = '歌曲不存在'
# 更改点击量
else:
song.hits += 1
db.session.add(song)
db.session.commit()
res = {}
res['status'] = 1
res['message'] = '播放次数加1'
return jsonify(res)
8.templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8">
<title>小林云音乐</title>
<link href="{{ url_for('static',filename='css/core.css')}}" rel="stylesheet">
<link href="{{ url_for('static',filename='css/pt_frame.css')}}" rel="stylesheet">
<link href="{{ url_for('static',filename='js/toolTip/tooltip.css')}}" rel="stylesheet">
<script type="text/javascript" src="{{url_for('static',filename='js/toolTip/tooltip.js')}}"></script>
<script type="text/javascript" src="{{url_for('static',filename='js/jquery-2.2.0.min.js')}}"></script>
<style>html, body {
overflow: hidden;
}</style>
<script>if (top != self)top.location = self.location;</script>
</head>
<body class="auto-1469062573613-parent auto-1469062573612-parent">
<div id="g-topbar" class="g-topbar">
<div class="m-top">
<div class="wrap">
<h1 class="logo"><a hidefocus="true" target="contentFrame" href="{{url_for('home.index')}}">甜橙云音乐</a></h1>
<ul class="m-nav j-tflag">
<li class="fst">
<span><a hidefocus="true" target="contentFrame" href="{{url_for('home.search')}}" data-module="discover" class="z-slt"><em>发现音乐</em></a></span>
</li>
<li>
<span><a target="contentFrame" href="{{url_for('home.collectList')}}"><em>我的音乐</em><sub class="cor"> </sub></a></span>
</li>
</ul>
{% if session['username'] %}
<div class="m-tophead f-pr j-tflag" >
<a onmouseover="tooltip.pop(this, '#textContent',{position:1, offsetX:0, effect:'slide'})" class="tooltip" style="color:#1C2021">您好,{{ session['username']}}</a>
</div>
<div style="display: none">
<div id="textContent" style="width: 75px; height: 45px;color:black">
{% if session['username'] == 'mr' %}
<a target="contentFrame" href="{{url_for('home.manageArtist')}}">后台管理</a>
{% else %}
<a target="contentFrame" href="{{url_for('home.modifyPassword')}}">修改密码</a>
{% endif %}
<br />
<a id="blogUrl" href="{{url_for('home.logout')}}">退出</a>
</div>
</div>
{% else %}
<div class="m-tophead f-pr j-tflag">
<a id="login" class="name f-thide f-fl f-tdn" style="color:#1C2021">登录</a>
<a id="register" class="name f-thide f-fl f-tdn" style="color:#1C2021">注册</a>
</div>
{% endif %}
</div>
</div>
<div class="m-subnav m-subnav-up f-pr j-tflag f-hide">
<div class="shadow"> </div>
</div>
<div id="g_nav2" class="m-subnav j-tflag">
<div class="wrap f-pr">
<ul class="nav">
<li><a hidefocus="true" target="contentFrame" href="{{url_for('home.index')}}" data-module="discover"
class="z-slt menuTab"><em>推荐</em></a></li>
<li><a hidefocus="true" target="contentFrame" href="{{url_for('home.toplist')}}" data-module="toplist"
class="menuTab"><em>排行榜</em></a></li>
<li><a hidefocus="true" target="contentFrame" href="{{url_for('home.styleList')}}" data-module="playlist"
class="menuTab"><em>曲风</em></a>
</li>
<li><a hidefocus="true" target="contentFrame" href="{{url_for('home.artistList')}}" data-module="artist"
class="menuTab"><em>歌手</em></a>
</li>
</ul>
</div>
</div>
</div>
<script>
$(".menuTab").bind("click", function(obj){
$('.menuTab').removeClass("z-slt");
obj.currentTarget.className='z-slt menuTab';
});
</script>
<iframe name="contentFrame" id="g_iframe" class="g-iframe" scrolling="auto" frameborder="0"
src="{{ url_for('home.contentFrame') }}">
</iframe>
<link href="{{url_for('static',filename='css/jplayer.blue.monday.min.css')}}" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="{{url_for('static',filename='js/jplayer/jquery.jplayer.min.js')}}"></script>
<script>
// 定义播放音乐的方法
function playMusic(name, id) {
$("#jquery_jplayer").jPlayer( "destroy" ); // 销毁正在播放的音乐
$("#jquery_jplayer").jPlayer({ // 播放音乐
ready: function(event) { // 准备音频
$(this).jPlayer("setMedia", {
title: name, // 设置音乐标题
mp3: "static/images/song/53.mp3" // 设置播放音乐
}).jPlayer( "play" ); // 开始播放
},
swfPath: "dist/jplayer/jquery.jplayer.swf", // IE8下的兼容播放
supplied: "mp3", // 音乐格式为mp3
wmode: "window", // 播放模式“window”
useStateClassSkin: true, // 设置默认样式
autoBlur: false, // 不支持模糊
smoothPlayBar: true, // 支持图标
keyEnabled: true, // 支持键盘
remainingDuration: true, // 支持动画
toggleDuration: true // 支持进度条
});
}
// 添加收藏
function addShow(id){
var username= "{{session['username']}}";
if(username=="null" || username==""){
layer.msg("收藏请先登录!",{icon:2,time:1000});
return;
}
$.ajax({
url: "{{url_for('home.collect')}}",
type: "get",
data: {
id: id
},
success: function(res){
if(res.status==1){
layer.msg(res.message,{icon:1})
}else{
layer.msg(res.message,{icon:2})
}
}
});
}
</script>
<div id="demo" style="z-index: 999; position: fixed;right:0;left:0;bottom:0;width:100%;">
<div id="jquery_jplayer" class="jp-jplayer">
</div>
<div id="jp_container_1" class="jp-audio" role="application"
aria-label="media player">
<div class="jp-type-single">
<div class="jp-details">
<div class="jp-title" aria-label="title">
暂无播放音乐
</div>
</div>
<div class="jp-gui jp-interface" style="margin-left:30% " >
<div class="jp-controls">
<button class="jp-play" role="button" tabindex="0">
play
</button>
</div>
<div class="jp-progress">
<div class="jp-seek-bar">
<div class="jp-play-bar"></div>
</div>
</div>
<div class="jp-volume-controls">
<button class="jp-mute" role="button" tabindex="0">
mute
</button>
<button class="jp-volume-max" role="button" tabindex="0">
max volume
</button>
<div class="jp-volume-bar">
<div class="jp-volume-bar-value"></div>
</div>
<div class="jp-duration" role="timer" aria-label="duration">
</div>
<div class="jp-time-holder">
<div class="jp-duration" role="timer" aria-label="duration">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="{{url_for('static',filename='js/layer/layer.js')}}"></script>
<script>
// 登录弹窗
$("#login").click(function () {
layer.open({
type: 2,
title: '登录',
shadeClose: true,
shade: 0.4,
area: ['700px', '550px'],
content: ['/login','no'] //iframe的url
});
});
// 注册弹窗
$("#register").click(function () {
layer.open({
type: 2,
title: '注册',
shadeClose: true,
shade: 0.4,
area: ['700px', '550px'],
content: ['/register','no'] //iframe的url
});
})
</script>
</body>
</html>
templates/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="{{ url_for('static',filename='css/core.css')}}" rel="stylesheet">
<link href="{{ url_for('static',filename='css/pt_frame.css')}}" rel="stylesheet">
<link href="{{ url_for('static',filename='css/login.css')}}" rel="stylesheet">
<script type="text/javascript" src="{{url_for('static',filename='js/jquery-2.2.0.min.js')}}"></script>
<script type="text/javascript" src="{{url_for('static',filename='js/layer/layer.js')}}"></script>
</head>
<body>
<div id="loginHtml">
<div class="left">
</div>
<div class="right" style="background: #f0f3f9 url('../../static/image/login-rightBg.jpg') no-repeat;">
<div class="respond">
<form method="post" action="{{url_for('home.login')}}" id="commentform" onsubmit="return false">
<div class="comment-login"></div>
<div class="comment-login" style="font-size:16px;margin-top:-40px">
<ul style="margin-top:100px">
<li class="form-inline">
<label><strong>用户名:</strong></label>
<input type="text" name="username" id="username" value="" tabindex="1" aria-required="true">
</li>
<li class="form-inline">
<label><strong>密    码:</strong></label>
<input type="password" name="pwd" id="pwd" value="" tabindex="2" aria-required="true">
</li>
</ul>
</div>
<div class="comment-login">
<input name="submit" type="submit" id="login" class="submitButton" tabindex="5" value="登录">
</div>
</form>
</div>
</div>
</div>
<script>
$('#login').click(function(){
var username = $('#username').val()
var pwd = $('#pwd').val()
if(username == ''){
layer.msg('请输入用户名',{icon:2,time:1000});
return false;
}
if(pwd == ''){
layer.msg('请输入密码',{icon:2,time:1000});
return false;
}
$.ajax({ // 使用Ajax异步提交
url: "{{ url_for('home.login') }}", // 提交到的URL
type: "POST", // 提交方式为GET
data:{username: username,pwd:pwd}, // 传递参数
dataType: "json", // 数据类型为json
success: function (res) { // 操作成功后执行逻辑
if (res.status == 1) {
layer.msg(res.message,{icon:1,time:2000},function(){
window.parent.location.reload(); // 从新加载父页面
var index = parent.layer.getFrameIndex(window.name); // 获取当frame标识
parent.layer.close(index); // 关闭当前页
});
} else {
layer.msg(res.message,{icon:2,time:2000}); // 提示已收藏
}
}
})
})
</script>
</body>
</html>
最后运行python app.py runserver
因为前端网页页面有点多,需要源代码可以私信博主
摘要:
大数据时代下,数据不断增长,为了迎合信息化时代的潮流和信息化安全的要求,利用互联网服务于其他行业,促进生产,已经是成为一种势不可挡的趋势。在音乐系统的要求下,开发一款整体式结构的音乐网系统,将顺应时代的发展,能够实现对需求变化的快速响应、系统稳定性的保障,能保证平台可持续、规模化发展的需求。
本系统的前端界面涉及技术主要有python、HTML等等,通过这些技术可以实现前端页面的美观和动态效果使符合广大群众的审美观,后台主要使用的技术有python编程语言,MySQL数据库、Flask框架,Flask框架可以通过ORM映射,最后渲染出用户喜欢的页面,本系统介绍了整个应用系统的设计思路,本文对每个部分进行了分析,本文设计的是用前后端结合做出的音乐网系统,用户和管理员都能进行使用,用户可以通过查询找到自己喜欢的歌曲进行播放收藏,管理员登陆后可以新增歌手和歌曲,更合理地管理音乐网系统,也能快速上线新的流行歌曲,供用户进行收听。
关键词:
音乐网系统;Flask;ORM;数据库;前端。
目录
第1章 绪论
1.1研究背景与意义
1.2 开发现状
1.3 论文结构与章节安排
第2章 相关技术
2.1 Flask框架介绍
2.2 ORM技术概述
2.3本章小结
第3章 需求分析
3.1 系统初步调查
3.2 总体需求
3.3 开发平台
3.4 本章小结
第4章 系统概要设计
4.1 系统设计概述
4.2 系统用例图
4.3 系统流程图
4.4 系统功能分析
4.5 本章小结
第5章 数据库设计
5.1数据库结构设计
5.1.1数据库表
第6章 系统具体实现
6.1 项目基础框架搭建
6.2 系统功能模块实现
6.2.1 推荐功能模块实现
6.2.2 用户登录功能实现
6.2.3用户注册功能实现
6.2.4 歌曲播放功能实现
6.2.5歌曲查询实现
6.2.6 排行榜功能实现:
6.2.7曲风功能实现
6.2.8 歌手功能实现
6.3 管理员功能实现
6.3.1 歌手管理功能实现
6.3.2 歌曲管理功能实现
6.4 本章小结
第7章 系统测试
7.1系统测试方法介绍
7.2 系统功能测试
7.3系统测试结果
7.4 音乐网系统实现全过程
7.5 本章小结
第8章.总结
8.1工作总结
参考文献
致谢
1.1研究背景与意义
随着我国网民的增加,也促进了网络音乐产业的发展。在这个大环境下,网络音乐行业的竞争也越来越激烈,音乐通过网络这个媒介更多的进入人们的日常工作休闲。随着网络技术的日趋成熟和普及,各类网站都快速出现在互联网上,音乐网站是其中较为流行和热门的一种。从音乐网站上发展而来的网络音乐是一种全新的音乐模式,它突破传统音乐的制作方法和传播模式的局限,音乐网站是网络音乐的发展平台。过去,音乐网站的功能比较单一,现在随着互联网的高速发展,用户对音乐网站的需求也越来越高,音乐网站也出现了较多采用优越的开发工具(如Flask、JSP、Django、Javascript等)来开发音乐网站,本课题所研究音乐网站就是想自己听听歌,把自己喜欢的歌收藏起来,从而给个人带来方便。
对于在线音乐网站来说,用户下载次数和访问量是至关重要的,因此,在线音乐网必须为用户提供大量,全面的,而且是最新的音乐,这样才能吸引用户,网站要提供流行歌曲和排行靠前的音乐,还需要为用户提供收藏服务。
我国在线音乐发展较早,开始于2002年百度上线MP3业务为用户免费提供音乐下载服务,紧接着酷狗、酷我和QQ音乐等主流平台相继成立,此时在线音乐仍处于起步阶段,市场乱象丛生,基本上处于无秩序发展阶段,09年文化部发布相关监管通知但收效甚微,导致我国在线音乐进入狂野生长阶段,盗版丛生,阻碍了在线音乐的健康发展,网易云音乐于此时成立,中国移动音乐行业的发展紧随互联网发展步伐,经过野蛮发展期、规范洗牌期而后步入了成熟稳定期,腾讯音乐集团和网易云音乐以“一超一强”形态攻占超过90%以上市场。随着用户的付费意愿提高、付费用户数不断增长,2017-2020年,中国移动音乐市场规模从66.3亿元增长到127.8亿元,年复
合增长率51.24%。随着政府加大国内音乐市场正版化、规范化力度和强度以及付费规模增长,市场规模增长可期。
1.3 论文结构与章节安排
本论文主要分为八个章节对课题进行论述,每个章节的内容如下所示:
- 绪论。主要讲述了对于当前音乐网的调研情况,介绍了此课题提出的背景和研究的意义,
- 相关介绍。介绍了此音乐网系统开发时所用的框架Flask和新型技术ORM作详细介绍。
- 需求分析。本章根据中国网数据得知,当前音乐网的发展趋势蓬勃发展,然后确定音乐网系统的总体需求,然后介绍开发音乐网所用到的开发工具做了详细概述。
- 系统概要设计。本章基于第三章的需求对音乐网管理系统作了全面的设计,首先设计了系统的总体架构,然后对音乐网管理系统的功能设计重点的作了介绍,接着对该套系统的数据库和ORM模型作了设计,最后系统的安全性作了分析。系统实现。按照系统的需求和设计说明书,实现了在线音乐网系统所有的功能模块。
- 数据库设计。介绍了在线音乐网数据库里面的数据表
第六章 系统具体实现。介绍了测试信息管理系统相关的理论知识;接着对音乐网系统从功能进行测试,保证系统的可用性、易用性和安全性。
第七章 系统测试。介绍了测试音乐网系统相关的理论知识;接着对在线音乐系统从功能进行测试,保证系统的可用性、易用性和安全性。
第八章 总结。对论文的主要工作进行了总结,分析本课题开发图书管理系统实现的功能和优势
Flask框架是一个用Python编写的轻量级Web应用程序框架,依赖于Werkzeug和Jinja2两个外部库。Werkzeug是一个WSGI工具包,用于接收和处理HTTP请求,匹配视图函数,支持Cookie和会话管理,交互式调试等功能。Jinja2是一个模板引擎,用于将响应结果渲染到模板文件,支持动态网页的呈现。Flask框架的核心构成简单,但具有很强的扩展性和兼容性,可以根据需要选择不同的数据库和其他功能扩展。Flask框架主要用于开发Web应用程序,例如网站或Web服务。
对象-关系映射(Object-Relational Mapping,简称ORM),面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。ORM框架的架构总览图如2.2所示。
本章了解了Flask框架和ORM映射的功能,知道Flask和ORM的关系,下面就对我们制作管理系统的逻辑思维更加明确,更容易做出管理系统。
系统初步调查的目标是从系统分析人员和管理人员的角度看新项目开发有无必要和可能,其基本内容包括:系统的基本情况、系统信息处理情况和系统资源情况。
系统初步调查了解到,音乐网站作为一种新兴的一种产业,以其便捷、时尚特点吸引越来越多的人们,抢占市场,并呈现出蓬勃发展的趋势。作为网络时代的产物,音乐网站具有很多新的特点,这些特点充满竞争力,以致成为传统商业的有力挑战者,引发商业革命。
网上音乐市场发展趋势,中国音乐市场的总规模由2017年的210亿元增加至2021年的约666亿元,2017年至2021年的复合年增长率为33.5%。大幅增长主要由同期中国数字音乐及音乐IP市场的快速扩张所推动。根据弗若斯特沙利文,预计2022年,中国音乐市场的总规模预计将达至762亿元。
由上可见,网上音乐网站以投资少、适应性广,成本低,与传统商店相比,网上音乐网站处于初级阶段,尚未形成真正意义的市场,相对于传统市场,有很大发展空间。
系统开发的特点就是实用。系统建设要求达到效率高,使用本系统来实现音乐网系统的使用。主要体现在以下几方面:
- 具备用户管理功能,包括但不限于用户注册、登录、退出
- 具备分类功能,根据不同地区、曲风、歌手类型对歌曲分类
- 具备在线听音乐功能,用户点击选中音乐即可播放
- 具备排行榜功能,根据用户点击歌曲播放次数进行排名
- 具备搜索功能,用户根据歌曲名称或歌手名搜索歌曲
- 具备收藏功能,用户登录之后便可收藏歌曲,可在“我的音乐”中查看
虚拟环境: virtualenv
数据库: PyMySQL驱动+MySQL
开发工具:PyCharm等
开发框架: Flask+ SQLAlchemy + Flask-Script+ Flask-Migrate+ jQuery+ blueprint等
根据市场分析和自己总体确定的需求,计算机对音乐网站进行管理,不仅为音乐网站的管理注入了新的生机,而且在运营过程中节省了大量的人力、物力、财力和时间,可以提高音乐网站的效率,随着计算机技术的发展,以及计算机在各个企事业单位中应用的普及,计算机强大的功能已为人们深刻认识。它在当今高速发展的信息时代占据着不可缺少的地位,作为计算机应用软件的一部分,使用计算机对音乐网站进行综合管理已经远远超过人工管理的效率。
系统设计是在系统分析的基础上由抽象到具体的过程,同时,还要考虑系统所实现的条件,系统设计的主要任务就是从管理信息系统出发,根据系统分析阶段对系统的逻辑功能的要求,并考虑经济、技术的条件,确保系统目标的实现。
- 用户可以根据自己喜欢来查询歌曲。
- 用户可以选择自己喜欢的歌曲进行播放。
- 用户可以对自己喜欢的歌曲进行收藏。
管理员的操作:
- 管理员可以根据用户不喜欢的歌曲进行删除。
- 管理员可以添加流行的歌曲。
- 管理员可以根据不同条件查询歌曲。
系统功能结构图:
用户的功能结构图:
管理员功能结构图:
根据系统和市场调研,音乐网系统前台分为五大模块,它们分别是推荐功能模块,歌曲显示模块,歌手显示模块,排行榜模块,用户使用模块,创建了一些简单的功能。下面是四大模块的功能:
推荐功能模块:根据最流行的歌曲进行推荐。
歌曲显示模块:分类显示最新的歌曲,按类别分页显示各类歌曲。
歌手显示模块:分类显示最流行的歌手,按照类别来显示各个地区的歌手。
歌曲排行榜模块: 播放次数排行。
用户使用模块:收藏歌曲,搜索歌曲,连续播放歌曲,查看歌手。
本系统后台分为2大模块,它们分别是歌曲管理模块和歌手管理模块,下面是它们的功能:
歌曲管理模块:可以根据歌曲名称和歌手名字和歌曲文件地址和分类进行新增歌曲,还可以在歌曲列表下面进行修改和删除。
歌手管理模块:可以根据歌手姓名和歌手分类和歌手照片进行增加歌手,也可以在歌手列表下进行删除和修改。
前台页面的概述:
访问在线音乐网站时,首先进入的是网站的前台页面,需要进行注册和登录才能进去网站,登录进去首先看到是推荐页面,然后点击各个功能都会弹出相关的功能。
后台页面的概述:
访问在线音乐网站后,需要在前台登录mr管理员账号后,再从上面网页上搜索127.0.0.1:5000/manager_artist_list才能进去后台网站,为了防止用户进去后台,进行非法操作,特意设置了只能管理员账号才能进入。
本章介绍了系统的原理图和整个系统的功能,还对整个系统的功能做了详细的概述,对整个系统的各个模块也做了详细的概述,可以让大家知道整个系统的功能和各个模块的功能。
5.1数据库结构设计
本系统采用Mysql作为访问数据库的服务器,用它来对数据进行存储,在数据库应用系统的开发过程中,数据库的结构设计是指数据库中各个表的设计,包括系统中的信息保存在哪个数据库中以及各个表之前的关系,数据库的好坏直接对应用系统实现的效果产生影响,好的数据库结构设计会减少数据库的存储,数据库的完整性比较高,系统具有较快的响应速度,简化基于此数据库的应用程序的实现。
综合实际来说,图书管理系统library的数据库主要包含如图所示的5张数据表。
用户和管理账号密码表:
歌手数据表:
歌曲数据表:
Flask项目搭建:
1、已有Python、PyCharm后,创建新项目(自定目录,建议启用VirtualEnv)新环境—解释器
- 可在命令行pip install安装Flask包,也可以在Pycharm的Python解释器下”+”安装,还要按照Flask的一些模块包,如下图所示:
6.2 系统功能模块实现
系统功能模块分为推荐功能模块,歌曲显示模块,歌手显示模块,排行榜模块,用户使用模块,管理歌手歌曲模块界面。
推荐功能模块是运用前端技术和flask框架的视图和数据库最后渲染出前端网页,管理员和用户账号都能登录也能看到,打开网页进入看到第一个页面就是推荐歌曲功能,把最流行的歌曲和歌手给你推荐出来,页面如下所示:
登录页面主要是用户和管理员先注册账号后,才能进行登录,登录功能中连接数据库了,如果账号密码可以到数据库查看,当账号密码错误则会提示账号密码错误,否则正常进入系统,页面如下图所示:
用户注册功能是先通过注册用户名和密码和确认密码,然后才能登录,才能进入网页,这是运用前端网页最后渲染模板实现的,页面如下图所示:
歌曲播放功能是用户登录后,进入页面后,随便点击一首歌曲他就能播放,也可以随时暂停,还可以随时控制音量,这是运用前端网页和flask框架的一些模板,最后渲染出来最后达到我们需要的效果,页面如下图所示:
6.2.5歌曲查询实现
歌曲查询功能,登录用户或者管理账号后点击发现音乐,上面有个搜索功能,随时可以通过歌曲名称找到自己喜欢的歌曲进行播放,页面如下图所示:
排行榜功能是点击排行榜进去后,通过播放次数最多的歌曲进行排序,还会推荐一些热门的歌手,页面如下所示:
曲风功能是根据不同歌手的唱歌风格来分成的,这里分为华语、欧美、日语、韩语、其他5种风格类型,页面如下所示:
歌手功能实现也是根据曲风进行分类的,这里分为华语、欧美、日语、韩语、其他5种歌手类型,点击每个类型都会弹出对应的歌手,页面如下图所示:
管理员功能主要分为歌曲管理和歌手管理方面,这两个类型可以让管理员更好的参与管理音乐网系统,还能随时上传流行歌曲来吸引人们。
歌手管理是管理员只有的权限,登录mr管理员的账号后,要在该网页上面加manager_artist_list才能进入该网页,进去后,可以对前台里面的歌手的信息随时修改,也能新增流行的歌手,页面如下所示:
歌手管理是管理员只有的权限,登录mr管理员的账号后,要在该网页上面加manager_artist_list才能进入该网页,进去后,可以对前台里面的歌曲的信息随时修改,也能新增流行的歌曲进去吸引用户,页面如下所示:
通过最初的需求,对每个功能实现的页面,和每个功能的操作做了详细的讲解,也可以知道这些功能实现所使用到的软件。
该系统在本地服务器上运行和调试,鉴于对系统的内部结构和处理算法的完全了解以及对系统功能的全面掌握对系统进行了测试。
模块功能测试使用正确数据、错误数据、边界数据进行测试,保证平台的正常运行。
1. 注册用户,输入自己的用户名和自己设置密码,两次密码要一致,最后点击注册。
2.登录用户,输入自己刚刚注册的用户名和密码进行登录,如密码不正确,会报账号密码错误。
3.登录成功进去的是推荐功能页面,点击歌曲,就会播放,点击收藏歌曲,可到我的音乐中查看。
4.点击发现音乐,进入的是一个搜索功能,点击搜索能找到自己喜欢的歌曲。
5.点击排行榜,可以看到流行歌手和播放次数最多的歌曲靠前。
6.点击曲风,会找到自己喜欢曲子风格的不同歌曲。
7.点击歌手,会根据风格找到自己喜欢的歌手人物。
8,登录管理员账号后,进入系统后,可以管理歌手和歌曲,更好的管理音乐网系统。
7.3系统测试结果
通过测试音乐网系统功能测试,已经检测完毕用户登录模块、用户注册模块、每个功能的运行测试,音乐网系统的功能都很正常,音乐网系统为了产品后期推广运营提供了强力的技术支撑。
文件夹结构
安装virtualenv:pip install virtualenv -i https://pypi.douban.com/simple(如果已安装virtualenv,这条命令可不执行,可使用 where virtualenv 查看是否已安装)
创建虚拟环境:virtualenv venv
激活虚拟环境 :venv\Scripts\activate
pip install -r requirements.txt -i https://pypi.tsinghua.edu.cn/simple
5. 创建music数据库,并根据自己的数据库账号密码配置数据库和数据库名
python manage.py db init # 创建迁移数据库,首次使用
python manage.py db migrate # 创建迁移脚本
python manage.py db upgrade # 把迁移应用到数据库中
- 运行 python manage.py runserver
测试过程中按照严格的方式进行测试,没有发现音乐网系统存在的问题,各个功能都已实现,实现这些功能,经历了2周的时间,保证了音乐网系统完成自己需要的需求,音乐网系统可以使用户拥有自己的音乐库,也能让管理更好管理音乐网系统。
经过两周的设计和开发,我对音乐网系统基本开发完毕,其功能能够符合应用需求,对于研发中出现的数据问题也通过百度解决了,通过这次设计能体会到自己技术的提升,还可以巩固上课学过的知识和学习新的语言并掌握,我们实习是做软件开发,刚开始我们在课程上只学过前端和js,我们软件开发只能用到这几个,后面经过几个月的实习,现在对js代码挺熟练应用起来,这个设计是经过自己在学校用心学的知识积累起来做成的一个毕业设计。
刚开发时,我遇到js上的许多问题,后面我专门用了两个月对js的学习,以及和比较厉害的同学一起讨论,最后能够解决,这个设计是完完整整的开发,在上半学期,flask的开发老师在课上只教一些简单的开发,我就从那时候慢慢了解它的原理,知道flask和django原理的开发,开发一个系统起来根本不难,但是加上js的系统开发就比较难啦,这个系统html+css+js+flask还有数据库开发出来的,这个设计可以给自己提供一个锻炼、提高的计划。
完成音乐网系统的各个功能和结构的设计, 本次项目让我更加深刻地体会到了前端框架的强大与便利,加深了我对Flask框架的认识,也更加了解了从客户端到服务器端,从请求到响应的过程,还有各种模型图的建立,把这些结合起来,为以后接手新的项目,处理打下基础。
参考文献
1.徐晓东. Flask 框架在音乐分析系统的应用研究[J]. 现代情报, 2019,39(4): 202-205.
2.韩玉涛, 杨慧君. 基于 Flask 的音乐系统播放设计与实现[J]. 计算机技术与发展, 2019, 29(7): 153-156+160.
3.马万里. 基于 Java的在线音乐系统设计与实现[J]. 计算机与数字工程, 2018(23): 53-54.
4.石静, 赵艳洪. 基于 Flask 的音乐系统设计与实现[J]. 现代电子技术, 2019(10): 177-178+181.
5.李亚军, 郑玲玲. 基于 Flask 的音乐系统开发[J]. 电子技术应用, 2016, 42(5): 110-114.
经过二个星期的设计和开发,在线音乐网系统基本开发完毕。其功能基本符合需求,能够完成歌曲播放,歌曲歌手推荐。界面提供浏览式,使用户可以得到一个属于自己的音乐网等系统。
这二周的开发,实际结合学习了一年多的前端知识结合起来的,使我提高了操作能力,虽然在设计过程中出现一些困难,但是在自身学习和老师的帮助下都克服了,在本次设计中,首先感谢我的指导老师,改论文是在指导老师张超老师的指导下完成的,老师理论知识都使我受益匪浅,他无论在理论和实际都给我很大帮助,使我技术得到提高,这些帮助在今后的工作和学习上都是一种巨大的帮助, 本次项目让我更加深刻地体会到了前端框架的强大与便利,加深了我对Flask框架的认识,也更加了解了从客户端到服务器端,从请求到响应的过程,在设计过程中,明白只有努力才能走向成功,再次感谢我的老师和同学们,时光如逝,岁月如初,转眼大学三年就要结束了,这三年中,在惠州经济职业技术学院留下很多美好的回忆。然而天下没有不散的宴席,我们即将各奔东西,走向社会,走向属于我们的未来,同时感谢惠州经济职业技术学院全体老师对我的教育和培养。
总结:
当我们完成了这个Flask音乐系统的开发,我们深刻地意识到,Flask框架的简洁、高效、灵活的特点,使得它成为了一个非常适合构建小型Web应用程序的工具。通过本次开发,我们不仅加深了对Flask框架的理解和应用,同时也提升了我们对Web应用程序的开发能力。
在这个音乐系统中,我们实现了用户注册、登录、注销、上传歌曲、搜索歌曲、播放歌曲等常见功能。这些功能的实现,离不开Flask框架提供的路由、模板、表单、数据库等功能模块。
在开发过程中,我们还遇到了一些问题,比如如何优化数据库查询效率、如何处理上传文件等。通过查阅Flask官方文档和相关资料,我们成功地解决了这些问题,并对Web应用程序的开发过程有了更深入的认识。
最后,我们要感谢Flask框架的开发者以及社区的支持和贡献,让我们能够轻松地开发出一个功能完备、美观实用的音乐系统。我们也希望通过本次开发,能够为其他想要学习Flask框架的开发者提供一些参考和帮助。