使用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 %}
- "stylesheet" href="{% static 'css/album.css' %}">
-
- class="header">
- "{% static 'images/logo.png' %}" class="logo" alt="">
-
-
-
- class="main_con">
- class="content">
- class="info_l">
- class="cover_out">
- "/media/{{info.cover}}" alt="" class="cover" data-src="info.cover" lazy="loaded">
- "{% static 'images/album_cover_record.png' %}" alt="" class="record">
-
-
class="intr">专辑简介
-
class="intr_txt">
- {{info.desc}}...
-
-
-
- class="info_r">
-
class="song_name flex_c">{{info.name}}
-
class="artist_name flex_c">{{song_info.singler.name}}
-
class="song_info">
- 专辑:class="tip">{{info.name}}
- 发行时间:{{song_info.addtime|date:'Y-m-d'}}
-
- class="btns">
-
- class="glyphicon glyphicon-play"> 立即播放
-
-
-
-
- class="glyphicon glyphicon-heart"> 收藏
-
-
- class="lyric lyricAll">
- {% for line in lyrics %}
- {% if forloop.counter == 1 %}
-
class="active">{{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})
这里需要把视图传递的变量进行渲染,只需要增加判断是否有数据,没数据显示无数据页面即可。
这里也有歌手信息需要判断,只需要处理路由跳转链接,其他不会报错就不处理了。
内容如下:
- class="all">
- {% if info %}
- {% else %}
- {% endif %}
- >
这里新增两部分内容:
处理跳转链接,即歌手相关信息的跳转链接;
二是增加判断显示无数据内容。
内容如下:
- class="main_con">
- class="con_l">
-
class="tabs flex_c">
-
- {% if info %}
- {% else %}
- {% endif %}
- class="active">简介
-
-
- class="child_view">
- {% if not info %}
-
- class="nodata flex_c">
- class="inner">
- "{% static 'images/nodata.png' %}"
- alt="" class="nodata_img">
- class="tip">
暂无相关数据
-
-
- {% else %}
-
class="tit">基本信息
- class="list_info">
- class="info_list flex_c">
- class="item_l">
- 姓名:class="text">{{info.name}}
-
-
- class="item_r">
- 英文名:class="text">{{info.english_name}}
-
-
- class="info_list flex_c">
- class="item_l">
- 性别:class="text">
- {% if info.gender %}
- 男
- {% else %}
- 女
- {% endif %}
-
-
-
- class="item_r">
- 国籍:class="text">{{info.country_name}}
-
-
- class="info_list flex_c">
- class="item_l">
- 生日:class="text">{{info.birthday}}
-
-
- class="item_r">
- 星座:class="text">{{info.constellation}}
-
-
- class="info_list flex_c">
- class="item_l">
- 身高:class="text">{{info.height}}cm
-
-
- class="item_r">
- 体重:class="text">{{info.weight}}kg
-
-
-
-
class="tit">个人简介
-
class="info">{{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)
- })
主要判断跳转链接进行无数据处理。
内容如下:
class="tabs flex_c">
-
- class="active">单曲
- {% if info %}
- {% else %}
- {% endif %}
-
还是歌手基本信息查询方式修改;分页处理修改;这里使用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())
原有的无数据页面不用修改,只需要判断单曲和简介的链接处理。
内容如下:
class="tabs flex_c">
-
- {% if info %}
- class="active">专辑
- {% else %}
- class="active">专辑
- {% endif %}
-
数据查询时,查询单条数据最好使用filter过滤器+first,
如果直接使用get查询,没有符合条件就会抛出异常,
或者也可以使用try对异常进行处理。
模板中要增加无数据提醒内容,这样用户体验会好一点。