在一个请求中更新用户配置文件和用户

Posted

技术标签:

【中文标题】在一个请求中更新用户配置文件和用户【英文标题】:Update user profile and user in one request 【发布时间】:2015-08-02 01:57:20 【问题描述】:

提前感谢您的关注。

目标:

简而言之:仅当单个视图发生更改时才更新 django 用户对象和自定义用户配置文件对象。

问题:

对于初学者来说,这是我第一次尝试做这样的事情,所以它可能非常简单,我只是忽略了它。

验证步骤似乎失败了,我收到一个 HTTP 400 错误,提示“用户名必须是唯一的”,即使我没有发送会更改当前用户用户名的更改。现在我可以使用 django-rest-auth 内置的视图来更新用户部分,然后只创建一个只更新配置文件的自定义视图。但这似乎很老套和愚蠢,但如果这是要走的路,那么我会这样做。

我尝试过的事情:

尝试了puts和patch。结果相同。 尝试覆盖 put 和 patch 方法以在验证之前从 request.data 中删除用户名字段(如果它相同),但这又给出了另一个错误,表明它是必需的。 尝试重写序列化程序中的更新方法,遇到了一个我不知道如何更新嵌套字段的问题。 谷歌搜索无止境。 考虑编写自定义验证器。但我不知道从哪里开始,我想让它尽可能简单,并且更喜欢内置的东西。

序列化器:

class UserSerializer(ModelSerializer):

    class Meta(UserDetailsSerializer.Meta):
        model = User
        fields = ('username', 'email', 'first_name', 'last_name')
        read_only_fields = ('email', )

class UserProfileSerializer(ModelSerializer):
    user = UserSerializer(required=True, many=False)
    games = UserGameProfileSerializer(required=False, many=True)

    class Meta:
        model = UserProfile
        fields = ('premium', 'user', 'games')

查看:

class UserProfileUpdateView(generics.UpdateAPIView):
    # authentication_classes = (authentication.TokenAuthentication,)
    # permission_classes = (permissions.IsAuthenticated,)
    serializer_class = UserProfileSerializer

    def get_queryset(self):
        return UserProfile.objects.filter(user__username__exact=self.request.user).all()

    def get_object(self):
        return UserProfile.objects.filter(user__username__exact=self.request.user).get()

【问题讨论】:

能否请您也分享一下您的模型,以便其他人更好地理解它 【参考方案1】:

免责声明

我终于弄明白了,我只是回答以供将来参考。我不确定这是完成任务的最佳做法还是最简单的方法。不过,这是我能想到的。

我将视图更改为更简单,而不是看起来很讨厌的过滤器查询,我发现我可以做一个 get 对象,然后说 user=self.request.user,这样就可以得到我需要的东西。

查看

class UserProfileUpdateView(generics.UpdateAPIView):
    authentication_classes = (authentication.TokenAuthentication,)
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = UserProfileSerializer

    def get_object(self):
        return UserProfile.objects.get(user=self.request.user)

然后在序列化程序中,我想出了如何更新嵌套对象,这正是需要做的。现在我意识到目前我只是在更新内置的 django 对象。但很快我将向用户配置文件添加更多字段,并且需要更新这些字段,如果用户对象发生更改,我想在同一个请求中更新它们。

在更新功能中,您可以使用self.data 访问请求数据,并且在那里我能够访问包含用户信息的字典。这样我就能够查询用户对象,然后使用 UserSerializer 我能够验证数据并调用 update 传递我查询的用户和来自序列化程序的验证数据。

序列化器

class UserProfileSerializer(ModelSerializer):
    user = UserSerializer(required=True, many=False)
    games = UserGameProfileSerializer(required=False, many=True)

    class Meta:
        model = UserProfile
        fields = ('premium', 'user', 'games')
        read_only_fields = ('premium', )

    def update(self, instance, validated_data):
        user_data = validated_data.pop('user')
        game_data = validated_data.pop('games')
        username = self.data['user']['username']
        user = User.objects.get(username=username)
        print user
        user_serializer = UserSerializer(data=user_data)
        if user_serializer.is_valid():
            user_serializer.update(user, user_data)
        instance.save()
        return instance

【讨论】:

仅供参考,在get_object 方法中,您可以简单地返回self.request.user 而不是return UserProfile.objects.get(user=self.request.user)

以上是关于在一个请求中更新用户配置文件和用户的主要内容,如果未能解决你的问题,请参考以下文章

如何在单个请求中使用 django 信号将数据保存在(用户和配置文件)表中?

保存用户配置文件和持久性

在jetstream更新表单中更新用户配置文件时,将用户的不同类型数据保存在不同的表中

配置文件对象 + 视图模型 + 更新用户配置文件 MVC C#

在 Laravel 中更新用户配置文件

更新 AD 组内的 sharepoint 用户配置文件