如何在Django表单中正确保存Dropzone文件并从数据库读取?
Django + Dropzone 拖拽上传解决方案
问题描述
我正在Django应用里实现拖拽上传功能,找不到Dropzone与Django结合的实用资料。之前用普通多文件上传功能一切正常,但拖拽上传更便捷,所以打算切换。目前已经把Dropzone集成到主表单中,但完全不清楚该如何保存这些文件,以及后续如何在模板中从数据库读取它们。本人JS经验不足,希望得到帮助。
现有代码
models.py
class Post(models.Model): author = models.ForeignKey( User, on_delete=models.CASCADE ) title = models.CharField( max_length=200, ) # 其他字段... class PostImages(models.Model): post = models.ForeignKey( Post, on_delete=models.CASCADE, related_name='images', ) file = models.FileField( upload_to="posts/images", validators=[], )
views.py
class PostCreateView(AuthRequiredMixin, SuccessMessageMixin, View): template_name = 'create_post.html' model = Post form = PostCreationForm success_url = reverse_lazy('index') success_message = _('Post created successfully') def get(self, request, *args, **kwargs): form = self.form() return render(request, self.template_name, {'form': form}) def post(self, request, *args, **kwargs): form = self.form(request.POST, request.FILES) if form.is_valid(): new_post = form.save(commit=False) new_post.author = request.user new_post.save() # 移除重复的form.save(),因为new_post已保存 # form.save() for img in request.FILES.getlist('images'): # 简化文件保存逻辑,直接使用UploadedFile对象 new_file = PostImages(post=new_post) new_file.file.save(img.name, img) new_file.save() messages.success(request, self.success_message) else: messages.error(request, 'Something went wrong!') return redirect(self.success_url)
forms.py
class PostCreationForm(ModelForm): # 注释原文件字段,改用Dropzone处理 # images = forms.FileField( # label='Images', # required=False, # help_text='Upload your images here!', # widget=forms.ClearableFileInput(attrs={'multiple': True}), # ) class Meta: model = Post fields = [ 'title', # 其他字段... ] labels = { 'title': 'Title', # 其他字段标签... }
create_post.html
<div class="card border-0 rounded shadow mb-5 p-5"> <h1>Create Post</h1> <form id="create-post" method="post" enctype="multipart/form-data"> {% csrf_token %} {% bootstrap_form form %} <div id="previewsContainer" class="dropzone"> <div class="dz-default dz-message"> <button class="dz-button" type="button"> Drop files here to upload </button> </div> </div> {% bootstrap_button content="Create"%} </form> </div> <script> Dropzone.autoDiscover = false; new Dropzone("#create-post",{ clickable: ".dropzone", url: "{% url 'create_post' request.user.slug %}", previewsContainer: "#previewsContainer", paramName: "images", maxFiles: 10, maxFilesize: 10, uploadMultiple: true, autoProcessQueue: false, // 携带CSRF令牌,避免验证失败 headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value }, init() { var myDropzone = this; // 绑定提交按钮触发放队列上传 this.element.querySelector("[type=submit]").addEventListener("click", function(e){ e.preventDefault(); e.stopPropagation(); // 无文件时直接提交表单,有文件则处理上传队列 if (myDropzone.getQueuedFiles().length > 0 || myDropzone.getAcceptedFiles().length > 0) { myDropzone.processQueue(); } else { this.form.submit(); } }); // 上传完成后自动跳转 myDropzone.on("queuecomplete", function() { window.location.href = "{% url 'index' %}"; }); } }); </script>
关键调整说明
后端文件保存优化
- 移除冗余的文件内容读取操作,直接使用
request.FILES中的UploadedFile对象保存,提升效率且减少出错概率。 - 删除重复的
form.save()调用,避免Post实例重复保存。
- 移除冗余的文件内容读取操作,直接使用
Dropzone配置完善
- 添加
headers配置,确保CSRF令牌被正确携带,通过Django的CSRF验证。 - 优化提交逻辑:区分有无上传文件的场景,保证表单和文件都能正确提交。
- 监听
queuecomplete事件,上传完成后自动跳转,避免用户重复操作。
- 添加
模板读取已上传图片
在文章详情页模板中,通过Post模型的related_name='images'关联,直接遍历展示图片:
{% for image in post.images.all %} <img src="{{ image.file.url }}" alt="Post image" class="img-fluid mb-3"> {% endfor %}
内容的提问来源于stack exchange,提问作者jmur
相关产品推荐
相关产品推荐

