web-dev-qa-db-ja.com

Django REST:複数の画像のアップロードとシリアル化

私は2つのモデルTaskTaskImageを持っています。これはTaskオブジェクトに属する画像のコレクションです。

Taskオブジェクトに複数の画像を追加できるようにしたいのですが、2つのモデルを使用しないとできません。現在、画像を追加しても、画像をアップロードして新しいオブジェクトを保存することはできません。

settings.py

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

serializers.py

class TaskImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = TaskImage
        fields = ('image',)


class TaskSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')
    images = TaskImageSerializer(source='image_set', many=True, read_only=True)

    class Meta:
        model = Task
        fields = '__all__'

    def create(self, validated_data):
        images_data = validated_data.pop('images')
        task = Task.objects.create(**validated_data)
        for image_data in images_data:
            TaskImage.objects.create(task=task, **image_data)
        return task

models.py

class Task(models.Model):
    title = models.CharField(max_length=100, blank=False)
    user = models.ForeignKey(User)

    def save(self, *args, **kwargs):
        super(Task, self).save(*args, **kwargs)

class TaskImage(models.Model):
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    image = models.FileField(blank=True)

ただし、投稿リクエストを行うと、

enter image description here

次のトレースバックが表示されます。

内部41のファイル「/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/core/handlers/exception.py」。response= get_response(request)

_get_response 187内のファイル「/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/core/handlers/base.py」。response= self.process_exception_by_middleware(e、request)

_get_response 185のファイル「/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/core/handlers/base.py」。response= wrapped_callback(request、* callback_args、** callback_kwargs)

ファイル "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/Django/views/decorators/csrf.py" in wrapped_view 58. return view_func(* args、** kwargs)

ビュー95のファイル "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/viewsets.py"。returnself.dispatch(request、* args、** kwargs)

ディスパッチ494のファイル「/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py」。response= self.handle_exception(exc)

Handle_exception 454のファイル「/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py」。self.raise_uncaught_exception(exc)

ディスパッチ491のファイル "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py"。response= handler(request、* args、** kwargs)

Create 21のファイル「/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/mixins.py」。self.perform_create(serializer)

Perform_create 152のファイル「/Users/gr/Desktop/PycharmProjects/godo/api/views.py」。serializer.save(user=self.request.user)

保存214内のファイル「/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/serializers.py」。self.instance= self.create(validated_data)

作成67のファイル「/Users/gr/Desktop/PycharmProjects/godo/api/serializers.py」。images_data= validated_data.pop( 'images')

例外タイプ:/ api/tasks /のKeyError例外値: 'images'

11
GRS

問題の説明
このステートメントimages_data = validated_data.pop('images')が原因で、例外の原因はKeyErrorでした。これは、検証されたデータにキーimagesがないためです。つまり、画像入力は郵便配達員からの画像入力を検証しません。

DjangoポストリクエストストアInMemmoryUpload in _request.FILES_なので、ファイルのフェッチに使用します。また、一度に複数の画像をアップロードする必要があります。したがって、(postmanで)画像をアップロードするときは、異なるimage_nameを使用する必要があります


serializerを次のように変更します。

_class TaskSerializer(serializers.HyperlinkedModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')
    images = TaskImageSerializer(source='taskimage_set', many=True, read_only=True)

    class Meta:
        model = Task
        fields = ('id', 'title', 'user', 'images')

    def create(self, validated_data):
        images_data = self.context.get('view').request.FILES
        task = Task.objects.create(title=validated_data.get('title', 'no-title'),
                                   user_id=1)
        for image_data in images_data.values():
            TaskImage.objects.create(task=task, image=image_data)
        return task
_



あなたの見方はわかりませんが、ModelViewSetを使用します
好ましいビュークラス

_class Upload(ModelViewSet):
    serializer_class = TaskSerializer
    queryset = Task.objects.all()
_


Postman Consoleenter image description here

DRF-Result

_{
        "id": 12,
        "title": "This Is Task Title",
        "user": "admin",
        "images": [
            {
                "image": "http://127.0.0.1:8000/media/Screenshot_from_2017-12-20_07-18-43_tNIbUXV.png"
            },
            {
                "image": "http://127.0.0.1:8000/media/game-of-thrones-season-valar-morghulis-wallpaper-1366x768_3bkMk78.jpg"
            },
            {
                "image": "http://127.0.0.1:8000/media/IMG_212433_lZ2Mijj.jpg"
            }
        ]
    }
_



[〜#〜]更新[〜#〜]
これがあなたのコメントに対する答えです。 Django _reverse foreignKey_は__set_を使用してキャプチャしています。これを参照してください 公式ドキュメント 。ここで、TaskおよびTaskImageOneToMany関係にあるため、1つのTaskインスタンスがある場合、この_reverse look-up_機能により、関連するすべてのTaskImageインスタンスを取得できます
ここに例があります

_task_instance = Task.objects.get(id=1)
task_img_set_all = task_instance.taskimage_set.all()
_

ここでこの_task_img_set_all_はTaskImage.objects.filter(task_id=1)と等しくなります

9
JPG

あなたが持っている read_onlyネストされたフィールドTaskImageSerializerでtrueに設定。したがって、validated_dataはありません。

0
kevswanberg