Django视图报错:Reverse for 'initiate_transcription'未找到的原因咨询
问题描述
在Django中实现用户在页面1上传文件后跳转至页面2,点击按钮触发转录服务,为每个用户上传生成唯一URL。但页面2的表单URL反向解析失败,报错NoReverseMatch,问题集中在模板代码{% url 'initiate_transcription' session_id %}。
urls.py
from django.urls import path from . import views urlpatterns = [ path("", views.transcribeSubmit, name = "transcribeSubmit"), path("init-transcription/<str:session_id>/", views.initiate_transcription, name = "initiate_transcription"), ]
views.py
@csrf_protect def transcribeSubmit(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): uploaded_file = request.FILES['file'] fs = FileSystemStorage() filename = fs.save(uploaded_file.name, uploaded_file) request.session['uploaded_file_name'] = filename request.session['uploaded_file_path'] = fs.path(filename) session_id = str(uuid.uuid4()) request.session['session_id'] = session_id return JsonResponse({'redirect': reverse('initiate_transcription', args=[session_id])}) else: # 原代码此处无逻辑,存在语法错误 pass else: form = UploadFileForm() # 原代码此处无返回,存在语法错误 pass @csrf_protect def initiate_transcription(request, session_id): if request.method == 'POST': try: # get the file's name and path from the session file_name = request.session.get('uploaded_file_name') file_path = request.session.get('uploaded_file_path') audio_language = request.POST.get('audio_language') output_file_type = request.POST.get('output_file_type') if file_name and file_path: with open(file_path, 'rb') as f: path_string = f.name transcript = transcribe_file(path_string,audio_language, output_file_type ) file_extension = ('.' + (str(file_name).split('.')[-1])) transcript_name = file_name.replace(file_extension, f'.{output_file_type}') transcript_path = file_path.replace((str(file_path).split('\\')[-1]), transcript_name) # Save transcript to a file if os.path.exists(transcript_path): file_location = transcript_path rawdata = open(file_location, 'rb').read(1000) result = chardet.detect(rawdata) charenc = result['encoding'] with open(file_location, 'r', encoding=charenc) as f: file_data = f.read() transcribed_doc = TranscribedDocument( audio_file=file_path, output_file=transcript_path ) transcribed_doc.save() # Create a FileResponse response = HttpResponse(file_data, content_type='text/plain; charset=utf-8') response['Content-Disposition'] = 'attachment; filename="' + transcript_name + '"' return response else: return JsonResponse({'status': 'error', 'error': 'No file uploaded'}) except Exception as e: error_message = f"Error occurred: {e}" return render(request, 'transcribe/transcribe-complete.html') def transcribe_file(path, audio_language, output_file_type ): #transcription logic
HTML页面1
<form method="post" action="{% url 'transcribeSubmit' %}" enctype="multipart/form-data" > {% csrf_token %} <label for="transcribe-file" class="transcribe-file-label"> ... </label> <!-- 文件输入框等表单元素 --> </form>
HTML页面2
<form id="initiate-transcription-form" method="post" action="{% url 'initiate_transcription' session_id %}" enctype="multipart/form-data"> {% csrf_token %} <!-- 语言选择、输出格式选择等表单元素 --> </form <!-- 原代码标签未闭合,存在语法错误 -->
JS页面1
const fileInput = document.querySelector('#transcribe-file'); fileInput.addEventListener('change', function (event) { if (event.target.files.length > 0) { console.log(fileInput.value); const fileName = event.target.value; const fileExtension = fileName.split('.').pop().toLowerCase(); const allowedExtensions = ['m4a', 'wav', 'mp3', 'mpeg', 'mp4', 'webm', 'mpga', 'ogg', 'flac']; if (!allowedExtensions.includes(fileExtension)) { const uploadField = document.querySelector('.transcribe-file-label'); const originalLabelText = uploadField.innerHTML; uploadField.style.color = '#ad0f0f'; uploadField.textContent = 'Invalid file type. Please try again'; setTimeout(function () { uploadField.style.color = ''; uploadField.innerHTML = originalLabelText; fileInput.value = ''; return; }, 5000); } else { const form = document.querySelector('form'); const xhr = new XMLHttpRequest(); const formData = new FormData(form); xhr.open('POST', form.action); xhr.upload.onprogress = function (event) { if (event.lengthComputable) { let percentComplete = (event.loaded / event.total) * 100; let progressBar = document.getElementById('myBar'); progressBar.style.width = percentComplete + '%'; console.log('Upload progress: ' + percentComplete + '%'); } }; xhr.onload = function () { if (xhr.status == 200) { console.log('Upload complete'); const response = JSON.parse(xhr.responseText); if (response.redirect) { window.location.href = response.redirect; } } else { console.error('Upload failed'); } }; xhr.send(formData); } } });
错误信息
NoReverseMatch at /transcribe/init-transcription/854eae4d-3167-4e45-8b17-20a14b142aad/ Reverse for 'initiate_transcription' with arguments '('',)' not found. 1 pattern(s) tried: ['transcribe/init\\-transcription/(?P<session_id>[^/]+)/\\Z']
解决方案
1. 修复视图模板上下文传递
initiate_transcription视图渲染页面2时,需将接收的session_id传入模板上下文,否则模板无法获取该变量导致URL解析失败:
# 修改views.py中initiate_transcription的最后一行 return render(request, 'transcribe/transcribe-complete.html', {'session_id': session_id})
2. 修复模板语法错误
页面2的表单标签未闭合,补充完整:
<form id="initiate-transcription-form" method="post" action="{% url 'initiate_transcription' session_id %}" enctype="multipart/form-data"> {% csrf_token %} <!-- 表单内容 --> </form>
3. 修复transcribeSubmit视图语法错误
原视图中POST请求表单验证失败、GET请求均无返回逻辑,补充完整:
@csrf_protect def transcribeSubmit(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): # 原有上传逻辑... return JsonResponse({'redirect': reverse('initiate_transcription', args=[session_id])}) else: # 处理表单验证失败情况 return JsonResponse({'status': 'error', 'error': 'File upload form is invalid'}) else: form = UploadFileForm() # GET请求渲染页面1 return render(request, 'transcribe/transcribe-submit.html', {'form': form})
4. 可选:增加session有效性验证
为防止非法访问,可在initiate_transcription视图开头验证session_id与当前会话匹配:
@csrf_protect def initiate_transcription(request, session_id): # 验证session_id合法性 if request.session.get('session_id') != session_id: return JsonResponse({'status': 'error', 'error': 'Invalid session'}) # 原有逻辑...
内容的提问来源于stack exchange,提问作者tthheemmaannii
相关产品推荐
相关产品推荐

