Django Admin上传Jupyter Notebook转HTML遇MultiValueDictKeyError求助
解决Django上传Jupyter Notebook时的MultiValueDictKeyError问题
我来帮你拆解问题并给出针对性方案——你遇到的MultiValueDictKeyError本质是request.FILES里找不到'notebook'这个键。结合你描述的「在Django Admin上传.json格式的Jupyter Notebook,转换为HTML后传递到模板」的需求,分两种场景处理:
场景1:你想通过前端页面上传文件(对应你当前写的视图逻辑)
如果你的目标是让普通用户通过前端表单上传Notebook,那需要修正以下几点:
1. 完善视图逻辑,避免抛出KeyError
直接用request.FILES['notebook']会在没有上传文件时直接报错,咱们改用get方法做兜底,同时判断请求方法:
# blog/views.py from django.shortcuts import render from django.http import HttpResponseBadRequest def upload_file(request): if request.method == 'POST': # 用get方法安全获取文件,避免KeyError notebook_file = request.FILES.get('notebook') if not notebook_file: return HttpResponseBadRequest("请选择要上传的Notebook文件") # 执行你的转换逻辑 notebook_html = converter(notebook_file) return render(request, 'test.html', context={'html': notebook_html}) # GET请求时返回上传表单页面 return render(request, 'upload_form.html')
2. 编写正确的上传表单模板
表单必须设置enctype="multipart/form-data"才能正确传递文件,创建templates/upload_form.html:
<form method="POST" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="notebook" accept=".json"> <button type="submit">上传并转换</button> </form>
场景2:你想在Django Admin后台上传时自动转换(更符合你描述的需求)
如果你的核心需求是管理员在后台上传Notebook后自动转HTML,那应该在Admin层处理转换逻辑,而不是前端视图:
1. 给模型新增字段存储转换后的HTML
先修改模型,添加一个字段来保存转换好的HTML内容:
# blog/models.py from django.db import models class FileUploader(models.Model): title = models.CharField(max_length=200) notebook = models.FileField(upload_to='notebooks/') notebook_html = models.TextField(blank=True, null=True) # 存储转换后的HTML def __str__(self): return self.title
2. 重写Admin的save_model方法处理转换
在Admin中重写save_model方法,在保存实例时自动执行转换:
# blog/admin.py from django.contrib import admin from .models import FileUploader class FileUploaderAdmin(admin.ModelAdmin): def save_model(self, request, obj, form, change): # 当新增文件或文件被修改时执行转换 if obj.notebook: # 读取上传的.json文件 with obj.notebook.open('r') as f: notebook_content = f.read() # 调用你的转换函数(这里假设converter可以处理文件对象或内容) notebook_html = converter(obj.notebook) obj.notebook_html = notebook_html # 调用父类方法完成保存 super().save_model(request, obj, form, change) admin.site.register(FileUploader, FileUploaderAdmin)
3. 编写视图展示转换后的HTML
现在可以写一个视图,根据实例的主键获取转换好的HTML并传递给模板:
# blog/views.py from django.shortcuts import render, get_object_or_404 from .models import FileUploader def notebook_page(request, pk): # 用get_object_or_404避免找不到实例的错误 upload_instance = get_object_or_404(FileUploader, pk=pk) return render(request, 'test.html', context={'html': upload_instance.notebook_html})
4. 更新URL配置
# blog/urls.py from django.urls import path from . import views urlpatterns = [ path('notebook/<int:pk>/', views.notebook_page, name='notebook_page'), ]
补充:转换函数的示例实现
如果还没写converter函数,可以用nbconvert库来处理Jupyter Notebook的转换:
from nbconvert import HTMLExporter import nbformat def converter(notebook_file): # 读取上传的Notebook文件 nb = nbformat.read(notebook_file, as_version=4) # 转换为HTML格式 exporter = HTMLExporter() html_content, _ = exporter.from_notebook_node(nb) return html_content
另外注意:模型里的upload_to='./notebooks/'可以简化为'notebooks/',Django会自动处理媒体文件的存储路径。
内容的提问来源于stack exchange,提问作者jfkoehler
相关产品推荐
相关产品推荐

