Получение файлов из массива FormData в серверной части django

#python #django #django-rest-framework

#python #django #django-rest-framework

Вопрос:

Я пытаюсь отправить POST-запрос.

Я пытаюсь опубликовать данные (FormData) из javascript, который содержит массив изображений, Команда print (request.data) в моей консоли показывает это:

  <QueryDict: 
     {'title': ['testTitle'], 'text': ['testText'], 
      'images': [<InMemoryUploadedFile: 486217.jpg (image/jpeg)>, 
                 <InMemoryUploadedFile: 344611.jpg (image/jpeg)>, 
                 <InMemoryUploadedFile: default.png (image/png)>]
              }>
  

код в django:models.py

 class Article(models.Model):

title = models.CharField(max_length=120)
text = models.TextField()
create_time = models.DateTimeField(default=datetime.utcnow, blank=True, 
              null=True)

def __str__(self):
    return self.title     

class ArticleImage(models.Model):
    article = models.ForeignKey(Article, related_name='images', 
              on_delete=models.CASCADE)
    img = models.ImageField(upload_to='article_images/')
    is_main = models.BooleanField(default=False,blank=True,null=True)
    create_time = models.DateTimeField(default=datetime.utcnow, blank=True, 
                  null=True)

def __str__(self):
    return  self.article.title
  

views.py

 class ArticleMixinView(generics.GenericAPIView,
                    mixins.ListModelMixin,
                    mixins.CreateModelMixin,
                    ...)
serializer_class = ArticleSerializer
queryset = Article.objects.all()
lookup_field = 'id'


def post(self, request):
    print(request.data)
    new_article = Article.objects.create(title=request.data.get('title'), 
                  text=request.data.get('text'))
    new_article.save()
    for img in request.data.get('images'):
        # article_img = ArticleImage(article=new_article,img=File(img), 
        #                             is_main=False )
        # article_img.save()

    return Response({
            'article': ArticleSerializer(new_article, 
                       context=self.get_serializer_context()).data

    }) 
  

Создание объекта Article работает нормально, но у меня возникли некоторые проблемы с этим массивом. Что не так, или как я могу получить изображения из объектов InMemoryUploadedFile????
Пожалуйста, любая помощь. Спасибо за пересылку)

Ответ №1:

Я думаю, что вы отправляете images в виде массива из своего интерфейса. Вы можете отформатировать их немного лучше, чтобы каждый объект массива соответствовал вашей ArticleImage модели. Например, каждый объект images ключа должен иметь файл, соответствующий img ключу (потому что это имя вашего поля в модели):

 <QueryDict: 
   {'title': ['testTitle'], 
    'text': ['testText'], 
    'images': [{'img': <InMemoryUploadedFile: 486217.jpg (image/jpeg)>},
             {'img': <InMemoryUploadedFile: 344611.jpg (image/jpeg)>}]
   }>
  

Теперь вы можете использовать ModelSerializer with many=True , чтобы выполнить эту работу за вас.

Например, создайте сериализатор для ArticleImage модели:

 class ArticleImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = ArticleImage
        fields = ('article', 'img', 'is_main', 'create_time')
        read_only_fields = ('article', 'is_main', 'create_time') # so that only `img` field comes from input
  

Теперь используйте это для сохранения ваших изображений в вашей модели:

 def post(self, request):
    print(request.data)
    images = request.data.pop('images')

    serializer = self.get_serializer_class(data=request.data) # why not use ArticleSerializer?
    serializer.is_valid(raise_exception=True)                 # this lets you validate if something is wrong with user's input
    new_article = serializer.save()                           # similar to Article.objects.create

    images_serializer = ArticleImageSerializer(data=images, many=True)  # only `img` comes from data
    images_serializer.is_valid(raise_exception=True)
    images_serializer.save(article=new_article, is_main=False) # adding additional fileds

    return Response(serializer.data) 
  

Этот код не тестировался, дайте мне знать, если что-то не работает должным образом. Надеюсь, это поможет.

Комментарии:

1. Я думаю, что я делаю что-то неправильно в своем методе создания FormData let data = new FormData(); const {imgList}=this.state; data.append(‘title’, event.target.elements.title.value,); data.append(‘text’,event.target.elements.content.value,); imgList.forEach(i =>{ data.append (‘images []’, i); }) Это нормально?