首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Django REST:上载和序列化多个图像

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

Stack Overflow用户
提问于 2018-02-12 22:02:16
回答 2查看 12.6K关注 0票数 16

我有两个模型TaskTaskImage,这是一个属于Task对象的图像集合。

我想要的是能够向我的Task对象添加多个图像,但是我只能使用两个模型来实现。目前,当我添加图片时,它不允许我上传它们并保存新的对象。

settings.py

代码语言:javascript
运行
复制
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

serializers.py

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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)

但是,当我请求发布邮件时:

我得到以下回溯:

将"/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/core/handlers/exception.py“文件保存在内部41中。响应=get_response(请求) "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/core/handlers/base.py“文件在_get_response 187中。响应= self.process_exception_by_middleware(e,请求) "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/core/handlers/base.py“文件在_get_response 185中。response =wrapped_callback(请求、*callback_args、**callback_kwargs) "/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/views/decorators/csrf.py“文件在wrapped_view 58中。返回view_func(*args,**kwargs) 查看95中的"/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/viewsets.py“文件。返回self.dispatch(请求,*args,**kwargs) 在调度494中文件"/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py“。响应= 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) 在调度491中文件"/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/views.py“。响应=处理程序(请求,*args,**kwargs) 创建21中的"/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/mixins.py“文件。Self.perform_create(串行化) "/Users/gr/Desktop/PycharmProjects/godo/api/views.py“文件在perform_create 152中。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(“图像”) 异常类型: KeyError at /api/任务/异常值:“图像”

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-13 08:52:53

对问题的描述

异常的起源是一个KeyError,因为这个语句

代码语言:javascript
运行
复制
images_data = validated_data.pop('images')

这是因为经过验证的数据没有键images。这意味着图像输入不验证来自邮递员的图像输入。

Django将请求存储在InMemmoryUpload中,因此我们使用它来获取文件。另外,您希望一次上传多个图像。因此,您必须使用不同的image_names,而您的图像上传(在邮递员中)。

将您的serializer更改为:

代码语言:javascript
运行
复制
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首选的视图类

代码语言:javascript
运行
复制
class Upload(ModelViewSet):
    serializer_class = TaskSerializer
    queryset = Task.objects.all()

邮递员控制台:

DRF结果:

代码语言:javascript
运行
复制
{
        "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捕获。看这个官方医生。在这里,TaskTaskImage处于OneToMany关系中,所以如果您有一个Task实例,就可以通过这个reverse look-up特性获得所有相关的TaskImage实例。

下面是一个例子:

代码语言:javascript
运行
复制
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)

票数 22
EN

Stack Overflow用户

发布于 2018-02-12 22:26:52

read_only嵌套字段中将TaskImageSerializer设置为true。所以那里不会有validated_data。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48756249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档