首页 文章

Django REST:上传和序列化多个图像

提问于
浏览
6

我有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

我得到以下回溯:

文件“/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/core/handlers/exception.py”在内部41. response = get_response(request)File“/ Applications / Anaconda /anaconda/envs/godo/lib/python3.6/site-packages/django/core/handlers/base.py“in _get_response 187. response = self.process_exception_by_middleware(e,request)File”/ Applications / Anaconda / anaconda / envs / godo / lib / python3.6 / site-packages / django / core / handlers / base.py“在_get_response 185. response = wrapped_callback(request,* callback_args,** callback_kwargs)File”/ Applications / Anaconda / anaconda /在wrapped_view 58中的envs / godo / lib / python3.6 / site-packages / django / views / decorators / csrf.py“ . 返回view_func(* args,** kwargs)文件”/ Applications / Anaconda / anaconda / envs / godo /lib/python3.6/site-packages/rest_framework/viewsets.py“在视图95中 . 返回self.dispatch(request,* args,** kwargs)文件”/ Applications / Anaconda / anaconda / envs / godo / lib / python3.6 / site-packages / rest_framework / views.py“在发送494.响应= self.handle_exception(exc)文件“/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py”在handle_exception 454中.self.raise_uncaught_exception(exc)文件“/ Applications /Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py“in dispatch 491. response = handler(request,* args,** kwargs)File”/ Applications / Anaconda / anaconda /envs/godo/lib/python3.6/site-packages/rest_framework/mixins.py“in create 21. self.perform_create(serializer)File”/Users/gr/Desktop/PycharmProjects/godo/api/views.py“在perform_create 152. serializer.save(user = self.request.user)文件“/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/serializers.py”中保存214. self .instance = self.create(validated_data)创建67中的文件“/Users/gr/Desktop/PycharmProjects/godo/api/serializers.py”.images_data = validated_data.pop('images')异常类型:/ api /上的KeyError任务/例外值:'图像'

2 回答

  • 0

    Description for the issue
    异常的起源是 KeyError ,因为这个陈述 images_data = validated_data.pop('images') . 这是因为验证数据没有密钥 images . 这意味着图像输入不会验证邮递员的图像输入 .

    Django在 request.FILES 中发布请求存储 InMemmoryUpload ,因此我们使用它来获取文件 . 此外,您希望一次上传多个图片 . 所以, you have to use different image_names while your image upload (in postman) .

    将你的_1694814改为这样,

    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
    

    我不想't know about your view, but i'我想使用 ModelViewSet
    prefferable view class

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

    Postman Console
    enter 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"
                }
            ]
        }
    

    UPDATE
    这是您的评论的答案 . 在django reverse foreignKey 正在使用 _set 捕获 . 看到这个official doc . 这里, TaskTaskImage 处于 OneToMany 关系中,因此如果您有一个 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)

  • 8

    您在 TaskImageSerializer 嵌套字段中将 read_only 设置为true . 所以那里没有validated_data .

相关问题