{{info.name}}
{{song_info.singler.name}}
专辑:{{info.name}} 发行时间:{{song_info.addtime|date:'Y-m-d'}}
{{line}}
{% else %}{{line}}
{% endif %} {% empty %}暂无歌词
{% endfor %}使用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 %}
{{info.name}}
{{song_info.singler.name}}
专辑:{{info.name}}
发行时间:{{song_info.addtime|date:'Y-m-d'}}
{% for line in lyrics %}
{% if forloop.counter == 1 %}
{{line}}
{% else %}
{{line}}
{% endif %}
{% empty %}
暂无歌词
{% endfor %}
{% 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})
这里需要把视图传递的变量进行渲染,只需要增加判断是否有数据,没数据显示无数据页面即可。
这里也有歌手信息需要判断,只需要处理路由跳转链接,其他不会报错就不处理了。
内容如下:
{% if info %}
全部
{% else %}
全部
{% endif %}
>
这里新增两部分内容:
处理跳转链接,即歌手相关信息的跳转链接;
二是增加判断显示无数据内容。
内容如下:
{% if not info %}
暂无相关数据
{% else %}
基本信息
姓名:{{info.name}}
英文名:{{info.english_name}}
性别:
{% if info.gender %}
男
{% else %}
女
{% endif %}
国籍:{{info.country_name}}
生日:{{info.birthday}}
星座:{{info.constellation}}
身高:{{info.height}}cm
体重:{{info.weight}}kg
个人简介
{{info.desc|safe}}
{% endif %}
歌手基本信息查询把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)
})
主要判断跳转链接进行无数据处理。
内容如下:
还是歌手基本信息查询方式修改;分页处理修改;这里使用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())
原有的无数据页面不用修改,只需要判断单曲和简介的链接处理。
内容如下:
数据查询时,查询单条数据最好使用filter过滤器+first,
如果直接使用get查询,没有符合条件就会抛出异常,
或者也可以使用try对异常进行处理。
模板中要增加无数据提醒内容,这样用户体验会好一点。