如何使用django modelform通过复制/粘贴上传图像?
How to upload an image through copy / paste using django modelform?
我是 django 的新手,正在尝试将 google 应用程序脚本 (GAS) webapp 迁移到 django。
我在 google 网站上的一个功能是从剪贴板捕获粘贴的图像并通过表单提交。这是通过以下形式的隐藏字段完成的:
<input type="hidden" name="summaryImage" id='summaryImage' value=''>
然后我捕获粘贴事件来填充这个隐藏的表单字段
/* Handle paste events */
function pasteHandler(e) {
if (e.clipboardData) {
// Get the items from the clipboard
var items = e.clipboardData.items;
if (items) {
// Loop through all items, looking for any kind of image
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
// We need to represent the image as a file,
var blob = items[i].getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById("summaryImage").value= reader.result;
}
reader.readAsDataURL(blob);
}
}
}
}
}
通过 google 提交的上述表单可以在服务器端 google 从表单中的 summaryImage 字段解析应用程序脚本 (GAS),如下所示:
var splitBase = form.summaryImage.split(','),
var type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var blob = Utilities.newBlob(byteCharacters, type);
现在,在 django 中,我无法复制它。我在 models.py 中创建了一个带有 ImageField 的模型:
...
image = models.ImageField(blank=True, null=True, verbose_name='Image')
...
并在 forms.py
中将小部件设置为 HiddenInput()
class MyForm(forms.ModelForm):
class Meta:
model = myModel
fields = '__all__'
widgets = {
'image': forms.HiddenInput()
}
...
甚至在捕获粘贴时,我将其设置为这个隐藏的图像字段:
document.getElementById("id_image").value= reader.result;
但是后来我无法提交表单,收到一条错误消息:
(Hidden field image) No file was submitted. Check the encoding type on
the form.
我搜索了很多但找不到任何关于在 django 中从剪贴板捕获粘贴图像的提及。这甚至可行吗?
感谢@allcaps 的建议,我找到了解决方案。
基本上我在我的模型中保留了 ImageField(图像),并分配了一个自定义小部件以仅显示 ID 为 id_image
的它。然后在表单中添加一个隐藏的输入字段image_container
来接收粘贴的数据。表单的保存功能被覆盖以创建文件并将其保存回 ImageField。
class PictureWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None):
if str(value) == '':
html1 = "<img id='id_image' style='display:block' class='rounded float-left d-block'/>"
else:
html1 = "<img id='id_image' style='display:block' class='rounded float-left d-block' src='" + settings.MEDIA_URL + str(value) + "'/>"
return mark_safe(html1)
class MyForm(forms.ModelForm):
image_container = forms.CharField(required=False, widget=forms.HiddenInput())
class Meta:
model = MYMODEL
fields = '__all__'
widgets = {
'image': PictureWidget(),
}
def save(self, commit=True):
# check image_container data
self.instance.image.delete(False)
imgdata = self.cleaned_data['image_container'].split(',')
try:
ftype = imgdata[0].split(';')[0].split('/')[1]
fname = slugify(self.instance.title)
self.instance.image.save('path/%s.%s' % (fname, ftype), ContentFile(imgdata[1].decode("base64")))
except:
pass
return super(MyForm, self).save(commit=commit)
我是 django 的新手,正在尝试将 google 应用程序脚本 (GAS) webapp 迁移到 django。
我在 google 网站上的一个功能是从剪贴板捕获粘贴的图像并通过表单提交。这是通过以下形式的隐藏字段完成的:
<input type="hidden" name="summaryImage" id='summaryImage' value=''>
然后我捕获粘贴事件来填充这个隐藏的表单字段
/* Handle paste events */
function pasteHandler(e) {
if (e.clipboardData) {
// Get the items from the clipboard
var items = e.clipboardData.items;
if (items) {
// Loop through all items, looking for any kind of image
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
// We need to represent the image as a file,
var blob = items[i].getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById("summaryImage").value= reader.result;
}
reader.readAsDataURL(blob);
}
}
}
}
}
通过 google 提交的上述表单可以在服务器端 google 从表单中的 summaryImage 字段解析应用程序脚本 (GAS),如下所示:
var splitBase = form.summaryImage.split(','),
var type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var blob = Utilities.newBlob(byteCharacters, type);
现在,在 django 中,我无法复制它。我在 models.py 中创建了一个带有 ImageField 的模型:
...
image = models.ImageField(blank=True, null=True, verbose_name='Image')
...
并在 forms.py
中将小部件设置为 HiddenInput()class MyForm(forms.ModelForm):
class Meta:
model = myModel
fields = '__all__'
widgets = {
'image': forms.HiddenInput()
}
...
甚至在捕获粘贴时,我将其设置为这个隐藏的图像字段:
document.getElementById("id_image").value= reader.result;
但是后来我无法提交表单,收到一条错误消息:
(Hidden field image) No file was submitted. Check the encoding type on the form.
我搜索了很多但找不到任何关于在 django 中从剪贴板捕获粘贴图像的提及。这甚至可行吗?
感谢@allcaps 的建议,我找到了解决方案。
基本上我在我的模型中保留了 ImageField(图像),并分配了一个自定义小部件以仅显示 ID 为 id_image
的它。然后在表单中添加一个隐藏的输入字段image_container
来接收粘贴的数据。表单的保存功能被覆盖以创建文件并将其保存回 ImageField。
class PictureWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None):
if str(value) == '':
html1 = "<img id='id_image' style='display:block' class='rounded float-left d-block'/>"
else:
html1 = "<img id='id_image' style='display:block' class='rounded float-left d-block' src='" + settings.MEDIA_URL + str(value) + "'/>"
return mark_safe(html1)
class MyForm(forms.ModelForm):
image_container = forms.CharField(required=False, widget=forms.HiddenInput())
class Meta:
model = MYMODEL
fields = '__all__'
widgets = {
'image': PictureWidget(),
}
def save(self, commit=True):
# check image_container data
self.instance.image.delete(False)
imgdata = self.cleaned_data['image_container'].split(',')
try:
ftype = imgdata[0].split(';')[0].split('/')[1]
fname = slugify(self.instance.title)
self.instance.image.save('path/%s.%s' % (fname, ftype), ContentFile(imgdata[1].decode("base64")))
except:
pass
return super(MyForm, self).save(commit=commit)