我正在开发一个项目,该项目的功能是用户可以使用拖放功能上传他的多张图片。我正在使用 Django-python 进行开发。我已经在 django 模板中实现了拖放功能,但是在提交表单数据时出现图像错误。
我的 Html 模板代码是:
<form id="newUserForm" name="newUserForm" data-abide action="{% url 'saveNewUserInfo'%}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="section"></div>
some input fields
<!-- The div for uploading the images -->
<div class="dropzone" style="border: 1px solid red;"></div>
<input type="submit" value="save">
</form>
我正在使用 dropzone.js 来实现拖放和排序
错误以 MultiValueDictKeyError at/saveNewUserInfo/, Exception Value: "'file'"
的形式出现
我的模型是:
class CustomerProfile(models.Model):
customer_id = models.CharField(db_column='customer_id', primary_key=True, max_length=20)
first_name = models.CharField(db_column='first_name', max_length=30, blank=True, null=True)
last_name = models.CharField(db_column='last_name', max_length=30,blank=True,null=True)
user_name = models.CharField(db_column='user_name', max_length=50,unique=True)
phone_number = models.CharField(db_column='phone_number', max_length=15,blank=True,null=True)
email_id = models.EmailField(db_column='email_id', max_length=50,blank=True, null=True)
user_image1 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image1', max_length=100)
user_image2 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image2', max_length=100)
user_image3 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image3', max_length=100)
user_image4 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image4', max_length=100)
user_image5 = models.ImageField(upload_to=IMAGES_PATH, db_column='user_image5', max_length=100)
表单.py
class CustomerInfoForm(forms.ModelForm):
class Meta:
model = CustomerProfile
请建议如何将 dropzone 多个图像存储到这些图像字段中。感谢您的建议..
最佳答案
很高兴你解决了这个问题。我花了几个小时解决这个问题:
使用 dropzone 的主要问题是一旦文件被放入其中,它就会开始上传。因此图片不会与表单数据的其余部分一起上传。
为了解决这个问题,我必须使用以下设置以编程方式创建 dropzone 对象:
$(document).ready(function(){
var list_of_files = new Array();
Dropzone.autoDiscover = false; //prevent dropzone to automatically discover the dropzone object in your html
$("div#dropzone").dropzone({
uploadMultiple: true, // allow multiple upload
autoProcessQueue: false, // prevent dropzone from uploading automatically
url: "/", //dropzone needs a url attribute or it complains, what value you put here does not really matter. It is only purpose is to prevent a javascript error message from chrome console
maxFiles: 5, //set max uploads to 5 since you only have 5 image files in your model
init: function(){
//everytime a file is uploaded, save the file object
//for later use
this.on("addedfile", function(file)
{
if (list_of_files.length < 5)
{
list_of_files.push(file)
console.log("file added");
}
});
}
});
// the following function override the "submit" button in the form
$(document).on("click", "button", function(e){
e.preventDefault() //prevent the form from submitting
console.log('num of files: ' + list_of_files.length);
var formData = new FormData(); // construct our own upload data
var inputs = $("#newUserForm input");
//get all of the data from textboxes
$.each(inputs, function(obj, v){
var name = $(v).attr("name")
var val = $(v).val();
console.log('name: ' + name + ' value: ' + val);
formData.append(name, val);
});
//get the file object from dropzone and put it into our formdata
for(i=0;i<list_of_files.length;i++)
{
formData.append('user_image'+(i+1), list_of_files[i]);
}
var request = new XMLHttpRequest();
request.open("POST", "/"); //config your post url here
request.send(formData); //send the post request to server
});
});
这是模板文件:
<form id="newUserForm" name="newUserForm" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% if form %}
{% for field in form %}
<p>{{ field.label_tag }} {{ field }}</p>
{% endfor %}
{% endif %}
<!-- The div for uploading the images -->
<div id="dropzone" class="dropzone"></div>
<button id='save'> save </button>
</form>
我还在 forms.py 中添加了排除项(这样这些字段就不会出现在我们的模板中,我们有 dropzone 来替换它们):
class CustomerInfoForm(forms.ModelForm):
class Meta:
model = CustomerProfile
exclude=('user_image1','user_image2','user_image3','user_image4','user_image5')
上面的所有代码都是将每个文本框中的数据和图像一起提交到您的 views.py 一步
这是views.py:
def index(request):
if request.method == 'POST':
form = CustomerInfoForm(request.POST)
if (form.is_valid()):
instance = form.save(commit=False)
#request.FILES contains all of the uploaded images
#key is 'user_image1', 'user_image2', value is the image file in memory
for key, value in request.FILES.iteritems():
a_path = '/a/b'
save_uploadfile_to_disk(a_path, file)
setattr(instance, key, a_path) //I made up the path here
form.save() //save the form for real
#do not forget to return a response
else:
print form.errors #for debugging only
else:
form = CustomerInfoForm()
context = {'form': form}
return render(request, 'test_dropzone/index.html', context)
def save_uploadfile_to_disk(full_path, file):
with open(full_path, 'w+') as destination:
for chunk in file.chunks():
destination.write(chunk)
我使用 Django 1.8 测试了这个解决方案并且它有效。我检查了数据库,路径已经正确写入记录。
现在,反射(reflection)这个解决方案,它有点违背了使用 dropzone 的目的。因为用户无法在选择文件后立即上传照片。
既然你也解决了这个问题。请发布您的解决方案,我期待从您那里学到新的东西:)
关于javascript - 如何使用 Dropzone 为多个图像字段在 Django 中上传多个图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28623094/