2014-08-28 88 views
2

我想使用djangorestframework更新模型。我不需要更新所有字段,所以我使用PATCH。但是,在我的表單中,我也有一個圖像字段(稱爲'徽標'),這是我的模型所必需的。當我嘗試「修補」對象並且不爲該字段選擇新圖像時,drf會拋出錯誤('logo':'此字段是必需的')。如何使用djangorestframework更新ImageField/FileField?

我知道當使用django表單時,文件字段會得到一個特殊的處理,這意味着如果它們已經有一個值,那麼提交一個空的文件字段的表單將保留舊的值。有沒有辦法使用djangorestframework序列化器來做到這一點?

更好地瞭解一些代碼:

# models.py 
class Brand(models.Model): 
    name = models.CharField(_('name'), max_length=250) 
    logo = models.ImageField(upload_to='brands/') 

# serializers.py 
class BrandSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Brand 
     fields = (
      'id', 
      'name', 
      'logo', 
     ) 

# detail.html 
<form method="post" enctype="multipart/form-data"> 
    {%csrf_token%} 

     <input name="name" type="text" maxlength="30" value="{{ brand.name }}"/> 
     <input name="logo" type="file" accept="image/*"/> 

    <input name="_method" type="hidden" value="PATCH"> 
    <input type="submit" value="Update"/> 

</form> 

盡我所能想出現在是調用序列化之前刪除我request.DATAlogo條目。我很好奇,如果有人知道更好的解決方案。謝謝。

回答

3

嘗試Link希望完全你會得到解決方案。 或看到這個凱德,希望完全這將爲你工作。

class ImageSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = Brand 
     fields = ('name', 'logo') 
    def saveImage(self, imgFileUri): 
     #parse dataUri and save locally, return local path 
     return 'somewhereOverTheBlah' 

    def restore_fields(self, data, files): 

     reverted_data = {} 

     if data is not None and not isinstance(data, dict): 
      self._errors['non_field_errors'] = ['Invalid data'] 
      return None 

     for field_name, field in self.fields.items(): 
      """ 
      So it is iterating over the fields to serialize, when we find the file field 
      do something different (in this case look for the fileUri field, handle it and replace 
      it inside of the reverted_data dictionary with the intended file field 
      """ 

      if(field_name == 'file'): 
       field_name = 'dataUri' 
       field = fields.CharField() 
       try: 
        # restore using the built in mechanism 
        field.field_from_native(data, files, field_name, reverted_data) 
        # take the dataUri, save it to disk and return the Path 
        value = reverted_data[field_name] 
        path = self.saveImage(value) 
        # set the file <Path> property on the model, remove the old dataUri 
        reverted_data['file'] = path 
        del reverted_data[field_name] 

       except ValidationError as err: 
        self._errors[field_name] = list(err.messages) 
      else: 
       field.initialize(parent=self, field_name=field_name) 
       try: 
        field.field_from_native(data, files, field_name, reverted_data) 
       except ValidationError as err: 
        self._errors[field_name] = list(err.messages) 

     return reverted_data