将 .update 与嵌套序列化程序一起使用到 post 图片

Using .update with nested Serializer to post Image

我有一个 ImageField。当我使用 .update 命令更新它时,它没有正确保存。它验证 returns 成功保存,并表示它很好。但是,图像永远不会保存(我没有像其他图片那样在我的 /media 中看到它),并且稍后提供时,它位于 /media/Raw%@0Data 没有图片的地方。当使用 post 存储图像时,它会正确存储。知道出了什么问题吗,它与嵌套序列化程序有关吗?

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),然后是更新命令。那不是根据模型正确保存图像。

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)

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

Finally, realize that update() does an update at the SQL level and, thus, does not call any save() methods on your models, nor does it emit the pre_save or post_save signals (which are a consequence of calling Model.save()).

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

The file is saved as part of saving the model in the database, so the actual file name used on disk cannot be relied on until after the model has been saved.

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

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

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