我有两个模型Task
和TaskImage
,这是一个属于Task
对象的图像集合。
我想要的是能够向我的Task
对象添加多个图像,但是我只能使用两个模型来实现。目前,当我添加图片时,它不允许我上传它们并保存新的对象。
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)
但是,当我请求发布邮件时:
我得到以下回溯:
将"/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/任务/异常值:“图像”
发布于 2018-02-13 08:52:53
对问题的描述
异常的起源是一个KeyError
,因为这个语句
images_data = validated_data.pop('images')
这是因为经过验证的数据没有键images
。这意味着图像输入不验证来自邮递员的图像输入。
Django将请求存储在InMemmoryUpload
中,因此我们使用它来获取文件。另外,您希望一次上传多个图像。因此,您必须使用不同的image_names,而您的图像上传(在邮递员中)。
将您的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()
邮递员控制台:
DRF结果:
{
"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
和TaskImage
处于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)
发布于 2018-02-12 22:26:52
在read_only
嵌套字段中将TaskImageSerializer
设置为true。所以那里不会有validated_data。
https://stackoverflow.com/questions/48756249
复制相似问题