You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django应用中实现单个<audio>标签切换播放不同音频

实现点击轮播歌曲在单个

我正在开发一个音乐流网站,首页有歌曲轮播组件,希望点击歌曲时能在单个HTML <audio> 标签中播放对应的音频。请问该如何实现?是否需要编写JavaScript函数?如果需要,函数应如何编写?


我的HTML代码:

<div class="main-carousel" data-flickity='{"groupCells":5 , "contain": true, "pageDots": false, "draggable": false, "cellAlign": "left", "lazyLoad": true}'>
    {% for i in songs %}
        <div class="carousel-cell">
            <section class="main_song">
                <div class="song-card">
                    <div class="containera">
                        <img src="{{i.image}}" id="A_{{i.id}}" alt="song cover">
                        <div class="overlaya"></div>
                        <div>
                            <a class="play-btn" href="...?" id="{{i.id}}"><i class="fas fa-play-circle fa-2x"></i></a>
                            {% if user.is_authenticated %}
                                <div class="add-playlist-btn">
                                    <a id="W_{{i.song_id}}" title="Add to Playlist" onclick="showDiv(this)"></a>
                                </div>
                            {% endif %}
                        </div>
                    </div>
                </div>
                <div>
                    <p class="songName" id="B_{{i.id}}">{{i.name}}</p>
                    <p class="artistName">{{i.artist}}</p>
                </div>
            </section>
        </div>
    {% endfor %}
</div>
<audio preload="auto" controls id="audioPlayer">
    <source src=...?>
</audio>

我的models.py代码:

class Song(models.Model):
    song_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50)
    artist = models.CharField(max_length=50)
    album = models.CharField(max_length=50, blank=True)
    genre = models.CharField(max_length=20, blank=True, default='Album')
    song = models.FileField(upload_to="songs/", validators=[FileExtensionValidator(allowed_extensions=['mp3', 'wav'])], default="name")
    image = models.ImageField(upload_to="songimage/", validators=[FileExtensionValidator(allowed_extensions=['jpeg', 'jpg', 'png'])], default="https://placehold.co/300x300/png")
    data = models.DateTimeField(auto_now=False, auto_now_add=True)
    slug = models.SlugField(unique=True)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['name']

解决方案

核心结论

必须编写JavaScript函数来实现,核心逻辑是:点击播放按钮时,获取对应歌曲的音频地址,更新单个<audio>标签的资源并触发播放。

1. 修改HTML播放按钮

给每个播放按钮添加自定义属性data-song-url,用来存储歌曲的音频文件地址(Django中可通过{{i.song.url}}直接获取),同时设置href为javascript:void(0)避免无效跳转:

<a class="play-btn" href="javascript:void(0)" data-song-url="{{ i.song.url }}" id="{{i.id}}">
  <i class="fas fa-play-circle fa-2x"></i>
</a>

简化<audio>标签(JS会自动覆盖资源地址):

<audio preload="auto" controls id="audioPlayer"></audio>

2. 编写JavaScript逻辑

使用事件委托绑定点击事件,适配动态生成的歌曲内容,无需给每个按钮单独绑定事件:

// 获取全局音频播放器元素
const audioPlayer = document.getElementById('audioPlayer');
// 获取轮播容器
const carouselContainer = document.querySelector('.main-carousel');

// 监听轮播容器内的点击事件
carouselContainer.addEventListener('click', function(e) {
  // 找到点击的播放按钮(点击图标时向上查找父级按钮)
  const targetPlayBtn = e.target.closest('.play-btn');
  if (!targetPlayBtn) return;

  // 阻止默认跳转行为
  e.preventDefault();

  // 获取当前歌曲的音频地址
  const targetSongUrl = targetPlayBtn.dataset.songUrl;
  if (!targetSongUrl) return;

  // 更新音频播放器的资源地址
  audioPlayer.src = targetSongUrl;

  // 触发播放,处理浏览器阻止自动播放的异常
  audioPlayer.play().catch(error => {
    console.error('音频播放失败:', error);
  });
});

3. 关键说明

  • 事件委托:通过父容器统一处理所有播放按钮的点击,后续动态加载的歌曲也能自动生效。
  • closest()方法:确保用户点击播放图标(<i>标签)时也能触发事件,避免操作死角。
  • 错误处理:部分浏览器会阻止未交互页面的自动播放,用catch捕获异常可避免控制台报错。

内容的提问来源于stack exchange,提问作者Federico Monetti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:47:33