使用.update和嵌套的Serializer发布图像

时间:2015-06-22 06:18:45

标签: django rest django-models django-rest-framework imagefield

我有一个ImageField。当我使用.update命令更新它时,它没有正确保存。它验证,返回成功的保存,并说它是好的。但是,图像永远不会保存(我不会在我的/媒体中看到它,就像我在做其他图片一样),当它稍后提供时,它位于/ media / Raw%@ 0Data,其中没有图片。使用帖子存储图像时,它会正确存储。知道什么是错的,它是否与嵌套的序列化器有关?

class MemberProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = MemberProfile
        fields = (
            'profile_image',
            'phone_number',
            'is_passenger',
            'is_owner',
            'is_captain',
            'date_profile_created',
            'date_profile_modified',
        )
class AuthUserModelSerializer(serializers.ModelSerializer):
    member_profile = MemberProfileSerializer(source='profile')

    class Meta:
        model = get_user_model()
        fields = ('id',
                  'username',
                  'password',
                  'email',
                  'first_name',
                  'last_name',
                  'is_staff',
                  'is_active',
                  'date_joined',
                  'member_profile',
                  )

    def update(self, instance, validated_data):
        profile_data = validated_data.pop('profile')
        for attr, value in validated_data.items():
            if attr == 'password':
                instance.set_password(value)
            else:
                setattr(instance, attr, value)
        instance.save()
        if not hasattr(instance, 'profile'):
            MemberProfile.objects.create(user=instance, **profile_data)
        else:
            #This is the code that is having issues
            profile = MemberProfile.objects.filter(user=instance)
            profile.update(**profile_data)
        return instance

在上面,您可以看到profile = MemberProfile.objects.filter(user = instance),然后是update命令。这不是根据模型正确保存图像。

class MemberProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, unique=True, related_name='profile')
    profile_image = models.ImageField(
        upload_to=get_upload_path(instance="instance",
                                  filename="filename",
                                  path='images/profile/'),
        blank=True)

1 个答案:

答案 0 :(得分:1)

如文档中所述,.update()不会为每个匹配的模型调用模型.save()或触发post_save / pre_save信号。它几乎直接转换为SQL UPDATE语句。 https://docs.djangoproject.com/en/1.8/ref/models/querysets/#update

  

最后,意识到update()在SQL级别进行更新,因此不会在模型上调用任何save()方法,也不会发出pre_save或post_save信号(这是调用Model的结果) .save())。

虽然文档中并不明显,但上传的文件也会作为模型.save()的一部分保存到磁盘:https://docs.djangoproject.com/en/1.8/topics/files/#using-files-in-models

  

该文件是作为将模型保存在数据库中的一部分保存的,因此在保存模型之前,不能依赖磁盘上使用的实际文件名。

这意味着您可以使用.update()直接更改存储在数据库列中的路径值,但它假定该文件已保存到该位置的磁盘中。

解决此问题的最简单方法是在两个路径中调用.save().create()已调用.save(),因此您需要将.update()版本更改为以下内容:

for key, value in update_data.items():
    setattr(instance.profile, key, value)
instance.profile.save(update_fields=update_data.keys())