2017-04-18 66 views
1

我很新与Django,并试图将谷歌应用程序脚本(GAS)的Web应用程序迁移到Django。如何通过复制/粘贴使用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); 
            } 
      } 
    } 
   } 
} 

在通过谷歌提交的上述形式,可以被解析服务器端的谷歌应用程序是从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

class MyForm(forms.ModelForm): 

    class Meta: 
     model = myModel 
     fields = '__all__' 
     widgets = { 
      'image': forms.HiddenInput() 
     } 
    ... 

设置widget中HiddenInput()和时甚至捕获的贴,我将其设置为这个隐藏的像场:

document.getElementById("id_image").value= reader.result; 

但后来我不能提交表单,收到错误消息:

(隐藏字段图像)未提交文件。检查 表单上的编码类型。

我搜索了一下,但找不到任何关于在django中从剪贴板捕获粘贴图像的任何提及。这甚至是可行的吗?

+2

在html中你输入的是隐藏的而不是图像。我想Django表单应该有一个CharField来接受粘贴的数据。在表单清理和保存方法中,将字符串数据转换为文件对象并使用它填充ImageField。 – allcaps

+0

@allcaps谢谢!它似乎工作并以字符串形式捕获数据。它看起来是这样的:数据:图像/ PNG; BASE64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAWCAYAAAAvg9c4AAAAMUlEQVRIDWP8 //// fwYqAyYqmwc2btRQ6ofqaJiOhimVQ2A0SVE5QBkYGEbDdIiEKQC6hwQozNWIkwAAAABJRU5ErkJggg == –

+0

@allcaps,但我想需要一个更大的字段来保存图像和CharField最大长度是不够的。我会尝试textarea。是否有更好的方法/字段类型来捕获这些数据? –

回答

1

感谢@ 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)