首页 > 解决方案 > Django 和 JavaScript:在 Javascript 文件中的对象列表中使用最后上传的文件

问题描述

编辑:这个问题开始是关于在 Django 中复制文件的问题,但结果证明可以直接实现实现我在 JavaScript 中访问文件的目标的更好方法。

原始问题

我想将最新上传的 mp3 文件从我的第一个模型(使用默认媒体文件夹)的对象列表中复制到一个名为“latest”的新文件夹中,并且我还想将新副本重命名为“latest.mp3”。这样我就有了一个已知的文件名,以便能够使用 Javascript 处理最新上传的文件。我还希望将原始、未更改的上传文件保留在我的第一个模型的对象列表中。

以下是我到目前为止所拥有的,但它不起作用:我没有从服务器或浏览器收到任何回溯错误。但是,副本不在“latest/”文件夹中。我相信我做错了不止一件事,我不确定是否应该将 CreateView 用于 SoundFileCopy 视图。我也不确定 SoundFileCopy 视图中的进程何时被触发:我假设它发生在我要求浏览器加载模板“process.html”时。

我正在使用 Django 3.1.7

如果有人可以帮助我,让我知道我需要在模型、视图和模板中添加什么以使其正常工作,我将不胜感激。

目前我的模型是:

class SoundFile(models.Model):
    sound_file = models.FileField()  
    created_on = models.DateTimeField(auto_now_add=True, null=True)
    last_modified = models.DateTimeField(auto_now=True, null=True)

class LatestFile(models.Model):
   New = models.FileField(upload_to="latest/")  

  

我的观点是:

class SoundUploadView(generic.CreateView):

   model = SoundFile
   fields = ['sound_file']
   template_name = 'upload.html'

import os
from django.core.files import File 

class SoundFileCopy(generic.CreateView):
    model = LatestFile
    fields = ['New']  
    uploaded_file = SoundFile.objects.last()
    latest_file = LatestFile() 
    latest_file.New = File(uploaded_file)
    latest_file.name = 'latest.mp3'
    latest_file.save()
    template_name = 'process.html'

我的模板是:

上传.html

{% block content %}

<h1><em>Upload mp3 file</em></h1>

<div class="container">
<form action="#" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.media }}
    {{ form.as_p }}
    <button class="btn btn-primary btn-sm" type="submit">Upload</button>
</form>
</div>
{% endblock %}

进程.html

{% block content %}

<h1>Process file</h1>
<p> {{ object_list.latest_file.name }} </p>
<p> Created on: {{ object_list.created_on}} </p>
<audio controls id="player"><source src="{{ object_list.latest_file.url }}"></audio>
<div>
    <a href="{{ object_list.latest_file.url }}" download  class="btn btn-dark float-left">Download</a>  
</div>  
{% endblock %}

谢谢

更新澄清:

我不一定需要将文件的新副本放在单独的文件夹中。

我希望能够使用 JavaScript(使用 Web Audio API)处理我的对象列表中最新上传的文件。

使用 Django 模板,我可以显示最新文件的属性,并通过在视图中过滤、返回SoundFile.objects.last()然后使用{{ object_list.sound_file.url}},{{ object_list.sound_file.name}}等将其加载到音频元素中,但我无法弄清楚如何将这些过滤后的结果传递到 JavaScript 文件中。

我能想到的唯一方法是使用我可以预测的文件名制作副本,然后在我的 JavaScript 文件中使用具有可预测文件名的副本。如果这不是必需的,并且有一种方法可以从 Django 获取过滤结果并在我的 JavaScript 文件中使用它,那就太棒了。

这是我一直在使用的示例 JavaScript 文件。它允许用户改变音乐的速度并改变循环播放的长度。它来自 Mozilla,主要由 chrisdavidmills 编写。它位于:https ://github.com/mdn/webaudio-examples/blob/master/decode-audio-data/index.html

您可以在函数中看到getData()anXMLHttpRequest()用于获取特定的声音文件(在本例中为“viper.mp3”)。我希望在我的对象列表中获取最后上传的文件来代替“viper.mp3”

// define variables

let audioCtx;
let source;
let songLength;

const pre = document.querySelector('pre');
const myScript = document.querySelector('script');
const play = document.querySelector('.play');
const stop = document.querySelector('.stop');

const playbackControl = document.querySelector('.playback-rate-control');
const playbackValue = document.querySelector('.playback-rate-value');
playbackControl.setAttribute('disabled', 'disabled');

const loopstartControl = document.querySelector('.loopstart-control');
const loopstartValue = document.querySelector('.loopstart-value');
loopstartControl.setAttribute('disabled', 'disabled');

const loopendControl = document.querySelector('.loopend-control');
const loopendValue = document.querySelector('.loopend-value');
loopendControl.setAttribute('disabled', 'disabled');

// use XHR to load an audio track, and
// decodeAudioData to decode it and stick it in a buffer.
// Then we put the buffer into the source

function getData() {
  if(window.webkitAudioContext) {
    audioCtx = new window.webkitAudioContext();
  } else {
    audioCtx = new window.AudioContext();
  }

  source = audioCtx.createBufferSource();
  request = new XMLHttpRequest();

  request.open('GET', 'viper.mp3', true);

  request.responseType = 'arraybuffer';


  request.onload = function() {
    let audioData = request.response;

    audioCtx.decodeAudioData(audioData, function(buffer) {
        myBuffer = buffer;
        songLength = buffer.duration;
        source.buffer = myBuffer;
        source.playbackRate.value = playbackControl.value;
        source.connect(audioCtx.destination);
        source.loop = true;

        loopstartControl.setAttribute('max', Math.floor(songLength));
        loopendControl.setAttribute('max', Math.floor(songLength));
      },

      function(e){"Error with decoding audio data" + e.error});

  }

  request.send();
}

// wire up buttons to stop and play audio, and range slider control

play.onclick = function() {
  getData();
  source.start(0);
  play.setAttribute('disabled', 'disabled');
  playbackControl.removeAttribute('disabled');
  loopstartControl.removeAttribute('disabled');
  loopendControl.removeAttribute('disabled');
}

stop.onclick = function() {
  source.stop(0);
  play.removeAttribute('disabled');
  playbackControl.setAttribute('disabled', 'disabled');
  loopstartControl.setAttribute('disabled', 'disabled');
  loopendControl.setAttribute('disabled', 'disabled');
}

playbackControl.oninput = function() {
  source.playbackRate.value = playbackControl.value;
  playbackValue.innerHTML = playbackControl.value;
}

loopstartControl.oninput = function() {
  source.loopStart = loopstartControl.value;
  loopstartValue.innerHTML = loopstartControl.value;
}

loopendControl.oninput = function() {
  source.loopEnd = loopendControl.value;
  loopendValue.innerHTML = loopendControl.value;
}

标签: javascriptdjango

解决方案


试试这个,

// get the <audio> element
const player = document.querySelector('#player');

// get first source element
source = player.getElementsByTagName('source')[0];

// get file url
url = source.src

request.open('GET', url, true);

或者

const url = document.querySelector('#player').getElementsByTagName('source')[0].src;

推荐阅读