如何使用django modelform通过复制/粘贴上传图像?

时间:2017-04-18 20:49:20

标签: django google-apps-script django-forms modelform

我对django很新,并尝试将Google应用脚本(GAS)webapp迁移到django。

我在谷歌网站上的一个功能是从剪贴板中捕获粘贴的图像并通过表单提交。这是通过以下形式的隐藏字段完成的:

<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提交时,可以在表单中的summaryImage字段中解析服务器端google apps脚本(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;

但是我无法提交表单,收到错误消息:

  

(隐藏的字段图像)没有提交文件。检查编码类型   形式。

我搜索了很多但是没有找到任何关于从django中的剪贴板捕获粘贴图像的提法。这甚至可行吗?

1 个答案:

答案 0 :(得分:1)

感谢@ allcaps的建议,我找到了解决方案。

基本上我将ImageField(图像)保留在我的模型中,并分配了一个自定义小部件,只显示标识为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)