2014-08-28 2 views
2

Я хочу обновить модель, используя djangorestframework. Мне не нужно обновлять все поля, поэтому я использую PATCH. Однако в моей форме у меня также есть поле изображения (называемое «логотип»), которое требуется для моей модели. Когда я пытаюсь «запланировать» объект, и я не выбираю новое изображение для этого поля, drf выдает ошибку («логотип»: «Это поле обязательно»).Как обновить ImageField/FileField с помощью djangorestframework?

Я знаю, что при использовании форм 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> 

Лучшее, что я мог придумать сейчас было удалить logo запись из моих request.DATA перед вызовом сериалайзер. Мне любопытно, знает ли кто-нибудь лучшее решение. Благодарю.

ответ

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