为何DATA_UPLOAD_MAX_MEMORY_SIZE在Django+TinyMCE环境下不生效?
在Django项目的settings.py中,已在非生产环境分支配置DATA_UPLOAD_MAX_MEMORY_SIZE = 209_715_200(200MB)和FILE_UPLOAD_MAX_MEMORY_SIZE = 209_715_200,但在TinyMCE文本字段中添加总大小超2.5MB的5张图片时,仍收到错误:Request body exceeded settings.DATA_UPLOAD_MAX_MEMORY_SIZE。
相关代码片段如下:
settings.py 关键配置
# ... 其他配置 ... if os.environ.get("PRODUCTION"): # 生产环境邮件配置 EMAIL_HOST = 'smtp.gmail.com' # ... 其余邮件配置 ... else: EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" DATA_UPLOAD_MAX_MEMORY_SIZE = 209_715_200 FILE_UPLOAD_MAX_MEMORY_SIZE = 209_715_200
views.py 编辑文章视图
def edit_post(request, slug): post = get_object_or_404(Post, slug=slug) if request.method == "POST": form = PostForm(request.POST, instance=post) if form.is_valid(): post.author = request.user.profile post.createdDateTime = timezone.now() if post.title != form.cleaned_data["title"]: post.slug = unique_slugify(post.title.lower()) if "thumbnail" in request.FILES: post.thumbnail = request.FILES["thumbnail"] post.save() return redirect('profile-details') else: form = PostForm(instance=post) return render(request, 'portfolio/edit_post.html', {'form': form})
HTML模板核心片段
<form method="POST" class="post-form" enctype="multipart/form-data"> {% csrf_token %} <!-- ... 表单其他字段 ... --> <div class="row box-text"> {{ form.text }} </div> <!-- ... 其他内容 ... --> </form>
1. 确保内存限制配置全局生效
你的DATA_UPLOAD_MAX_MEMORY_SIZE和FILE_UPLOAD_MAX_MEMORY_SIZE仅在非生产环境(PRODUCTION环境变量不存在时)加载。如果服务器运行在生产环境(比如PythonAnywhere),这两个配置不会生效,Django会使用默认值(2.5MB),这正是报错的核心原因。
修改settings.py,将这两个配置移到if-else分支外,确保所有环境都能加载:
# ... 其他配置 ... # 全局设置上传内存限制(200MB) DATA_UPLOAD_MAX_MEMORY_SIZE = 209_715_200 FILE_UPLOAD_MAX_MEMORY_SIZE = 209_715_200 if os.environ.get("PRODUCTION"): # 生产环境邮件配置 EMAIL_HOST = 'smtp.gmail.com' # ... 其余邮件配置 ... else: EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
2. 配置TinyMCE图片直传(避免Base64嵌入)
默认情况下,TinyMCE会将插入的图片转成Base64编码嵌入到textarea内容中,这会让POST请求体体积增加33%以上。改为直接上传图片到服务器,仅在内容中保存图片URL,可彻底规避请求体大小限制:
步骤1:修改TinyMCE配置
在settings.py的TINYMCE_DEFAULT_CONFIG中添加上传相关配置:
TINYMCE_DEFAULT_CONFIG = { # ... 原有配置 ... 'images_upload_url': '/upload-image/', # 指定上传接口 'images_upload_credentials': True, # 携带CSRF凭证 'images_file_types': 'jpeg,jpg,png,gif', # 允许的图片格式 }
步骤2:编写图片上传视图
在views.py中添加处理图片上传的视图:
from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt import os from django.conf import settings from uuid import uuid4 @csrf_exempt def upload_image(request): if request.method == 'POST' and request.FILES.get('file'): file = request.FILES['file'] # 生成唯一文件名避免重复 filename = f"{uuid4().hex}{os.path.splitext(file.name)[1]}" # 定义存储路径 save_dir = os.path.join(settings.MEDIA_ROOT, 'tinymce_images') os.makedirs(save_dir, exist_ok=True) file_path = os.path.join(save_dir, filename) # 分片保存文件 with open(file_path, 'wb+') as destination: for chunk in file.chunks(): destination.write(chunk) # 返回图片URL给TinyMCE return JsonResponse({ 'location': f"{settings.MEDIA_URL}tinymce_images/{filename}" }) return JsonResponse({'error': '无效请求'}, status=400)
步骤3:配置上传路由
在项目的urls.py中添加上传接口的路由:
from django.urls import path from . import views urlpatterns = [ # ... 其他路由 ... path('upload-image/', views.upload_image, name='tinymce_upload'), ]
3. 检查服务器层面的请求大小限制
如果部署在PythonAnywhere等平台,平台本身可能有默认请求大小限制(比如2MB),需要手动调整:
- 登录PythonAnywhere后台,进入Web选项卡,在"Max request size"处设置为200MB(209715200字节)
- 若使用Apache服务器,可在
.htaccess中添加:LimitRequestBody 209715200
内容的提问来源于stack exchange,提问作者1dlvb

