使用Python Django框架制作一个音乐网站,本篇主要是单曲详情页及对
之前开发歌曲详情无数据及分页不存在情况处理。
目录
单曲详情
单曲详情算是一个公共的页面,歌单、排行榜、专辑等都可跳转详情页,
显示相应单曲信息和歌词列表。
设置路由
这次不在设置参数,采用一种新的方式传参。
path('album/song', views.album_song, name='album_song'),
视图处理
引入库文件
接下来需要读取文件和django设置的媒体目录配置,所以要引用下面的类库。
import os
from django.conf import settings
读取歌词方法
通过文件函数读取os连接起来的django设置媒体目录和歌词文件的全路径。
因为查询返回的歌词文件路径是文件格式需要转化为字符串格式。
通过循环文件句柄,将读取的每一行放入列表中。
def read_lyric(path):
""" 读取歌词文件 """
f = open(os.path.join(settings.MEDIA_ROOT, str(path)), 'r', encoding='utf-8')
lines = []
for line in f:
lines.append(line)
f.close()
return lines
单曲详情视图
这里的参数改为使用request GET 方式读取相应名称参数。
下面通过filter过滤条件,之后first取一条符合条件数据。
歌词字段通过读取歌词方法返回内容判断并赋值;
最后通过locals函数把设置好的变量全都传递给模板。
def album_song(request):
""" 专辑中单曲详情 """
id = request.GET.get('id')
sid = request.GET.get('sid')
info = Album.objects.filter(id=id).first()
song_info = Singe.objects.filter(id=sid).first()
# 歌词处理
lyrics = []
if song_info:
lyrics = read_lyric(song_info.lyric)
return render(request, 'album/song.html', locals())
模板渲染
模板中主要渲染两部分内容:单曲信息+歌词列表及所属专辑信息。
{% extends 'common/base.html' %}
{% load static %}
{% block title %}我的音乐-单曲{% endblock title %}
{% block content %}
<link rel="stylesheet" href="{% static 'css/album.css' %}">
<!--导航条开始-->
<div class="header">
<img src="{% static 'images/logo.png' %}" class="logo" alt="">
<ul>
<li><a href="{% url 'player:index' %}">推荐</a></li>
<li><a href="javascript:void(0)">排行榜</a></li>
<li><a href="javascript:void(0)" class="selected">歌手</a></li>
<li><a href="javascript:void(0)">歌单</a></li>
</ul>
</div>
<!--导航条结束-->
<!--专辑内容开始-->
<div class="main_con">
<div class="content">
<div class="info_l">
<div class="cover_out">
<img src="/media/{{info.cover}}" alt="" class="cover" data-src="info.cover" lazy="loaded">
<img src="{% static 'images/album_cover_record.png' %}" alt="" class="record">
</div>
<p class="intr">专辑简介 </p>
<p class="intr_txt">
{{info.desc}}...
</p>
<div><a href="javascript:;" class="download bg_primary">
<i class="glyphicon glyphicon-download-alt"></i> 下载这首歌</a>
</div>
</div>
<!--单曲歌词列表开始-->
<div class="info_r">
<p class="song_name flex_c">{{info.name}}</p>
<p class="artist_name flex_c">{{song_info.singler.name}}</p>
<p class="song_info">
<span>专辑:</span><span class="tip">{{info.name}}</span>
<span>发行时间:{{song_info.addtime|date:'Y-m-d'}}</span>
</p>
<div class="btns">
<button class="play bg_primary">
<i class="glyphicon glyphicon-play"></i> <span>立即播放</span>
</button>
<button><i class="glyphicon glyphicon-plus"></i> <span>添加</span>
</button>
<button>
<i class="glyphicon glyphicon-heart"></i> <span>收藏</span>
</button>
</div>
<div class="lyric lyricAll">
{% for line in lyrics %}
{% if forloop.counter == 1 %}
<p class="active">{{line}}</p>
{% else %}
<p>{{line}}</p>
{% endif %}
{% empty %}
<p>暂无歌词</p>
{% endfor %}
</div>
</div>
<!--单曲歌词列表结束-->
</div>
</div>
<!--专辑内容结束-->
{% endblock content %}
无数据处理
歌手详情-基本信息
视图查询修改
原本使用get方式查询,这种方式可以获得一条符合条件的数据,缺点在于如果没有符合条件的数据,则会抛出异常;改为filter查询方式,这种方式会返回符合记录的集合。就算没有符合条件的也不会抛出异常,只会返回空集。还需要判断结果进行赋值。
内容如下:
def singer_detail(request, id):
""" 歌手详情-基本信息 """
infos = Singler.objects.filter(id=id)
if infos:
info = infos[0]
else:
info = False
return render(request, 'singer/detail.html', {'info': info})
模板判断无数据
这里需要把视图传递的变量进行渲染,只需要增加判断是否有数据,没数据显示无数据页面即可。
歌手头部公共信息
这里也有歌手信息需要判断,只需要处理路由跳转链接,其他不会报错就不处理了。
内容如下:
<span class="all">
{% if info %}
<a href="{% url 'player:singer_detail' info.id %}">全部</a>
{% else %}
<a href="javascript:void(0)">全部</a>
{% endif %}
> </span>
歌手基本信息模板
这里新增两部分内容:
处理跳转链接,即歌手相关信息的跳转链接;
二是增加判断显示无数据内容。
内容如下:
<div class="main_con">
<div class="con_l">
<ul class="tabs flex_c">
<li>
{% if info %}
<span class=""><a href="{% url 'player:singer_song' info.id 1 %}">单曲</a></span>
<span class=""><a href="{% url 'player:singer_album' info.id 1 %}">专辑</a></span>
{% else %}
<span class=""><a href="javascript:void(0)">单曲</a></span>
<span class=""><a href="javascript:void(0)">专辑</a></span>
{% endif %}
<span class="active">简介</span>
</li>
</ul>
<div class="child_view">
{% if not info %}
<!--设置无数据内容-->
<div class="nodata flex_c">
<div class="inner">
<img src="{% static 'images/nodata.png' %}"
alt="" class="nodata_img">
<div class="tip"><p>暂无相关数据</p></div>
</div>
</div>
{% else %}
<p class="tit">基本信息</p>
<div class="list_info">
<div class="info_list flex_c">
<div class="item_l">
<span>姓名:<span class="text">{{info.name}}</span></span>
</div>
<div class="item_r">
<span>英文名:<span class="text">{{info.english_name}}</span></span>
</div>
</div>
<div class="info_list flex_c">
<div class="item_l">
<span>性别:<span class="text">
{% if info.gender %}
男
{% else %}
女
{% endif %}
</span></span>
</div>
<div class="item_r">
<span>国籍:<span class="text">{{info.country_name}}</span></span>
</div>
</div>
<div class="info_list flex_c">
<div class="item_l">
<span>生日:<span class="text">{{info.birthday}}</span></span>
</div>
<div class="item_r">
<span>星座:<span class="text">{{info.constellation}}</span></span>
</div>
</div>
<div class="info_list flex_c">
<div class="item_l">
<span>身高:<span class="text">{{info.height}}cm</span></span>
</div>
<div class="item_r">
<span>体重:<span class="text">{{info.weight}}kg</span></span>
</div>
</div>
</div>
<p class="tit">个人简介</p>
<p class="info">{{info.desc|safe}}</p>
{% endif %}
</div>
</div>
</div>
歌手详情-单曲列表
视图查询修改
歌手基本信息查询把get查询改为filter过滤器查询。
分页数据也要处理无分页和分页超过最大分页情况。
内容如下:
def singer_song(request, id, page):
""" 歌手详情-单曲列表 """
# 歌手基本信息
info = Singler.objects.filter(pk=id).first()
song_list = Singe.objects.filter(singler_id=id).all()
# 实例化Paginator
paginator = Paginator(song_list, 20)
try:
res = paginator.page(page)
except PageNotAnInteger:
res = paginator.page(1)
except EmptyPage:
res = paginator.page(paginator.num_pages)
return render(request, 'singer/song_list.html', {
'info': info,
'songList': res,
'list_num': len(song_list)
})
模板判断无数据
主要判断跳转链接进行无数据处理。
内容如下:
<ul class="tabs flex_c">
<li>
<span class="active">单曲</span>
{% if info %}
<span><a href="{% url 'player:singer_album' info.id 1 %}">专辑</a></span>
<span><a href="{% url 'player:singer_detail' info.id %}">简介</a></span>
{% else %}
<span><a href="javascript:void(0)">专辑</a></span>
<span><a href="javascript:void(0)">简介</a></span>
{% endif %}
</li>
</ul>
歌手详情-专辑列表
视图查询修改
还是歌手基本信息查询方式修改;分页处理修改;这里使用locals优化传给模板的变量。
内容如下:
def singer_album(request, id, page):
""" 歌手详情-专辑列表 """
# 歌手基本信息
info = Singler.objects.filter(pk=id).first()
# 专辑列表
albumList = Album.objects.filter(singler_id=id).order_by('-id').all()
# 实例化Paginator
paginator = Paginator(albumList, 20)
try:
res = paginator.page(page)
except PageNotAnInteger:
res = paginator.page(1)
except EmptyPage:
res = paginator.page(paginator.num_pages)
list_num = len(res)
return render(request, 'singer/album_list.html', locals())
模板判断无数据
原有的无数据页面不用修改,只需要判断单曲和简介的链接处理。
内容如下:
<ul class="tabs flex_c">
<li>
{% if info %}
<span><a href="{% url 'player:singer_song' info.id 1 %}">单曲</a></span>
<span class="active">专辑</span>
<span><a href="{% url 'player:singer_detail' info.id %}">简介</a></span>
{% else %}
<span><a href="javascript:void(0)">单曲</a></span>
<span class="active">专辑</span>
<span><a href="javascript:void(0)">简介</a></span>
{% endif %}
</li>
</ul>
总结
数据查询时,查询单条数据最好使用filter过滤器+first,
如果直接使用get查询,没有符合条件就会抛出异常,
或者也可以使用try对异常进行处理。
模板中要增加无数据提醒内容,这样用户体验会好一点。