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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:47:06