javascript - 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;
}
解决方案
试试这个,
// 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;
推荐阅读
- mysql - 创建索引然后插入或插入然后创建索引?
- python - 将自定义格式数据加载到 splunk
- mysql - mysql unique 请问插入的顺序会改变吗?
- foundationdb - 手表永远不会在 FoundationDB 中触发
- wordpress - WordPress - 通过自动更新强化权限?
- android - MPAndroidChart Barchart:设置关联到高亮条的标签颜色
- vue.js - VueJS 定期检查全局函数
- testing - Testcafe:我将 testcafe 更新为 0.23.2,测试使执行时间增加了两倍
- javascript - 在循环中更改某些元素的样式
- merge - 避免 Git 对某个文件类型进行任何合并