首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Django Rest框架:禁止将TypeError直接分配到多到多集的前侧。

Django Rest框架:禁止将TypeError直接分配到多到多集的前侧。
EN

Stack Overflow用户
提问于 2022-05-08 12:29:38
回答 1查看 404关注 0票数 0

我有一个定制的User模型和一个由UserGroup通过模型链接的Group模型(许多模型与许多关系):

models.py

代码语言:javascript
运行
复制
class User(models.Model):
    username = models.CharField(primary_key=True, max_length=32, unique=True)
    user_email = models.EmailField(max_length=32, unique=False) # Validates an email through predefined regex which checks ‘@’ and a ‘.’
    user_password = models.CharField(max_length=32)
    user_avatar_path = models.CharField(max_length=64)

class Group(models.Model):
    group_id = models.AutoField(primary_key=True)
    group_name = models.CharField(max_length=32, unique=False)
    group_admin = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        related_name='my_groups'
        )
    members = models.ManyToManyField(
        User,
        related_name='groups', # The name to use for the relation from the related object back to this one.
        through='UserGroup' # Attaches a Junction table to the Many to Many relationship.
        )

class UserGroup(models.Model): # Manually specified Junction table for User and Group
    user = models.ForeignKey(
        User, 
        on_delete=models.CASCADE, 
        related_name='user_groups'
        )
    group = models.ForeignKey(
        Group, 
        on_delete=models.CASCADE, 
        related_name='user_groups'
        )

我试图将多个用户与一个组关联起来,使用PATCH请求更新组的members属性。使用以下GroupSerializer,当创建组时,我可以通过重写序列化程序的create函数将用户关联为组的成员:

serializers.py

代码语言:javascript
运行
复制
class GroupSerializer(serializers.ModelSerializer):
    members = MemberSerializer(many=True, required=False)
    group_admin = serializers.SlugRelatedField(slug_field='username', queryset=User.objects.all()) # A Group object is related to a User object by username

    class Meta:
        model = Group
        fields = ['group_id', 'group_name', 'group_admin', 'members']

    def create(self, validated_data): # Overriden so that when a group is created, the group admin is automatically declared as a member.
        group = Group.objects.create(**validated_data)
        group_admin_data = validated_data.pop('group_admin')
        group.members.add(group_admin_data)

        return group
    
    def update(self, instance, validated_data):
       members_data = validated_data.pop('members') # Comes from the request body, gets the members list
        #print('output: ' + str(members_data[0].items()))
        add_remove = self.context['add_remove'] # Comes from the View 
        if members_data is not None:
            if add_remove == 'add':
                for member in members_data:
                    instance.members.add(member['username'])
            elif add_remove == 'remove':
                for member in members_data:
                    instance.members.remove(member['username'])  
            
        return super().update(instance, validated_data)

当重写序列化程序的update函数时,我无法更新与组关联的成员。序列化程序是从以下GroupUpdate视图调用的:

views.py

代码语言:javascript
运行
复制
class GroupUpdate(generics.UpdateAPIView):
    serializer_class = GroupSerializer

    def get_object(self):
        queryset = Group.objects.all()
        group_id = self.kwargs['group_id']
        if group_id is not None:
            queryset = queryset.filter(group_id=group_id).first()
        return queryset

    def get_serializer_context(self): # Passes the URL paramters to the GroupSerializer (serializer doesn't have kwargs).
        context = super().get_serializer_context()
        context['add_remove'] = self.kwargs['add_remove']
        print(self.request.data)
        return context

    def perform_update(self, serializer):
        serializer=GroupSerializer(data=self.request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        return super().perform_update(serializer)

perform_update函数GroupUpdate中,我接收到以下内容:TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use members.set() instead.,但我不确定为什么会引发此错误,因为我能够以几乎相同的方式将用户与create函数中的某个组关联起来。

这就是修补程序请求作为JSON主体所具有的内容:

代码语言:javascript
运行
复制
{
    "members": [
        {
            "username": "small_man"
        }
    ]
}

self.request.data的输出为{'members': [{'username': 'small_man'}]}

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-08 14:14:36

在创建序列化程序时,应指定已更新对象的实例,否则序列化程序的保存方法将调用create而不是update

代码语言:javascript
运行
复制
def perform_update(self, serializer):
    instance = self.get_object() 
    serializer=GroupSerializer(instance, data=self.request.data, partial=True)
    serializer.is_valid(raise_exception=True)
    return super().perform_update(serializer)

顺便说一句,perform_update看起来是多余的,您可以删除它,因为序列化程序验证应该在不进行额外修改的情况下工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72160987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档