Django Rest FrameWork で配列やファイルを含むupdate処理について

# はじめに
<!-- 発端や概要を記載 -->
DRFで配列やファイル含むデータを送信する際に、multipart/form-dataで送信したが、PostManでもうまくいかず、FrontEnd側やPostManの使い方と思いこんでしまいはまってしまいました。私がやったやり方は以下のとおりです。

- multipart/form-dataで送信　※前提条件のとおりですが、Base64とか他にもやり方はあるそうです
- ファイルはFileFieldを使わない
- ViewSetで、createとupdateをオーバライドする　※Serializerでオーバライドする方法もあるそうですが、よく分かりませんでした。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [正解](#正解)
1. [補足](#補足)
1. [参考文献](#参考文献)

<!-- 各チャプター -->
<a id="#正解"></a>
# 正解
```Python:models.py
from django.db import models
from eqs.models import Eqs, EqTypes
class Infos(models.Model):
    titles = models.CharField(max_length=32)
    sammary = models.TextField(max_length=100)
    text = models.TextField()
    def __str__(self):
        return self.titles

class Files(models.Model):
     """
     ファイル格納用
     """
    Infos = models.ForeignKey('Infos', on_delete=models.CASCADE, related_name="files")
    filePath = models.CharField(primary_key=True, max_length=512)
    def __str__(self):
        return self.filePath
```
```Python:serializer.py
from rest_framework import serializers
from .models import Infos, Files

class InfosSerializer(serializers.ModelSerializer):
    files = serializers.StringRelatedField(many=True, read_only=True)
    class Meta:
        model = Infos
        fields = "__all__"
```
```Python:serializer.py
import os
from rest_framework import viewsets
from rest_framework import status
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from .models import Infos, Files
from .serializer import InfosSerializer

UPLOAD_DIR = 'media/' # mediaフォルダに格納するためのアップロードパス

class InfosViewSet(viewsets.ModelViewSet):
     queryset = Infos.objects.all()
     serializer_class = InfosSerializer

     def create(self, request, *args, **kwargs):
          info = Infos.objects.create()
          return self.serialize(request, info)

     def update(self, request, pk, *args, **kwargs):
          info = get_object_or_404(Infos, pk=pk)
          return self.serialize(request, info)

     def serialize(self, request, bugInfo):
          serializers = InfosSerializer(instance=Info, data=request.data, partial=True)
          serializers.is_valid(raise_exception=True)
          serializers.save()
          self.delFiles(request)
          self.setFiles(info, request)

          return Response(serializers.data, status.HTTP_200_OK)

     def setFiles(self, info, request):
          files = request.FILES.getlist('addFiles[]')

          for file in files:
               # ファイル保存処理
               path = os.path.join(UPLOAD_DIR, file.name)
               destination = open(path, 'wb')
               for chunck in file.chunks():
                    destination.write(chunck)
               destination.close

               # model保存処理
               if not os.path.exists(path):
                    continue
               else:
                    fileobj = Files.objects.create(filePath=path, infos=info)
                    fileobj.save()

     def delFiles(self, request):
          str_delFiles = request.POST.getlist('delFiles[]')

          for str_delFile in str_delFiles:
               fileobj = Files.objects.get(filePath=str_delFile)
               fileobj.delete()
               os.remove(str_delFile)
```

<a id="#補足"></a>
# 補足
## PostManでの確認方法
PostManでの配列の送信方法はkeyの後ろに「[]」を付ければOK(Advanced Rest Clientでも同じ)
![postman.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496025/bc7dbd59-f856-488d-6a26-807c18d47920.png)

## axiosでの送信方法

```JavaScript:save.js
// 一部抜粋
    save() {
      const editedId = this.editID;
      const formData = new FormData();

      Object.entries(this.editedItem).forEach(([key, value]) => {
        if (Array.isArray(value)) {
          value.forEach((v, i) => {
            formData.append(key + '[]', v);
          });
        } else {
          formData.append(key, value);
        }
      });
      try {
        if (editedId === -1) {
          axios.post('/Info/', formData, config).then(postRes => {
            this.editedItem.id = postRes.data;
            axios.get('/Info/' + postRes.data.id + '/').then(getRes => {
              this.infos.push(getRes.data);
            });
          });
          this.close();
        } else {
          axios
            .put('/Info/' + this.editedItem.id + '/', formData, config)
            .then(putRes => {
              axios.get('/Info/' + putRes.data.id + '/').then(getRes => {
                Object.assign(this.infos[editedId], getRes.data);
              });
            });
          this.close();
        }
      } catch (error) {
        alert('DBに保存されませんでした\n' + error);
      }
    },

```

<a id="#参考文献"></a>
# 参考文献
- [Postmanで配列とファイルをPOSTする話](https://tech.briswell.com/entry/2020/08/21/174405)
- [axiosにFormDataを使ってArrayデータを送信する](https://qiita.com/k5690033/items/717f280266dee3e1f741)