我有2个模型Task
和TaskImage
,它们是属于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)
但是,当我发布帖子请求时:
我得到以下追溯:
文件 “/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/core/handlers/exception.py” 在内心 41. response = get_response(request)
文件 “/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/core/handlers/base.py” 在_get_response中 187. response = self.process_exception_by_middleware(e,request)
文件 “/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)
文件 “/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/django/views/decorators/csrf.py” 在wrapped_view中 58. return 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. response = 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” 在发货 491. response = handler(request,* args,** kwargs)
文件 “/Applications/Anaconda/anaconda/envs/godo/lib/python3.6/site-packages/rest_framework/mixins.py” 在创造 21. self.perform_create(序列化程序)
文件“/Users/gr/Desktop/PycharmProjects/godo/api/views.py”in 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)
文件“/Users/gr/Desktop/PycharmProjects/godo/api/serializers.py”in 创建 67. images_data = validated_data.pop('images')
异常类型:/ api / tasks / Exception值的KeyError:'images'
答案 0 :(得分:13)
问题描述
由于此声明KeyError
,异常的起源是images_data = validated_data.pop('images')
。这是因为验证数据没有密钥images
。这意味着图像输入不会验证邮递员的图像输入。
Django在InMemmoryUpload
中发布请求存储request.FILES
,因此我们使用它来获取文件。此外,您希望一次上传多个图片。因此,在上传图片时(邮差),您必须使用不同的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()
{
"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
进行捕获。见official doc。在这里,Task
和TaskImage
处于OneToMany
关系中,因此,如果您有一个Task
实例,则可以通过此{{1}获取所有相关的TaskImage
实例功能
这是一个例子
reverse look-up
此处task_instance = Task.objects.get(id=1)
task_img_set_all = task_instance.taskimage_set.all()
将等于task_img_set_all
答案 1 :(得分:0)
您在read_only
嵌套字段中将TaskImageSerializer
设置为true。所以那里没有validated_data。