如何使用M2M发布数据?

时间:2016-10-26 14:38:31

标签: django rest django-rest-framework

我想编写一个API端点,为2个模型创建数据,通过多对多关系链接在一起。我们假设这些模型是UserGroup

要求:

  • 两个涉及的模型尚不存在,因此我无法使用pk来描述它们。
  • 端点可以根据需要创建任意数量的用户/组。

如果这些模型之间的关系是1-> N(即用户可以在N组中,但是一组可以与1个用户相关),那么解决方案将是微不足道的:

'user1': {'name': "robert",
         'groups': [{'name': 'group1'}, {'name': 'group2'}]
         }
'user2': {'name': "jean",
         'groups': [{'name': 'group3'}, {'name': 'group4'}]
         }

但是因为它是一个M2M,我应该如何做到这一点?嵌套不起作用:

'user1': {'name': "robert",
         'groups': [{'name': 'group1'}, {'name': 'group2'}]
         }
'user2': {'name': "jean",
         'groups': [{'name': 'group2'}, {'name': 'group3'}]
         }

在这种情况下,服务器可能会尝试创建4个组而不是3个。另外,我正在重复尝试指定两个对象两次。

请注意,这里,一个组对象是一个简单的模型,但在我的实际情况中,该对象是一个复杂的对象,具有多级嵌套,所以我不能重复自己。

你会如何解决这个问题? 我想到的唯一解决方案是进行两次HTTP调用,而不是一次。

注意:我使用的是Django和Django Rest Framework。

1 个答案:

答案 0 :(得分:0)

假设您的用户模型中有groups = ManyToManyField(Group),则以下情况应该有效。

在用户序列化程序中定义字段groups = GroupSerializer()(您必须将GroupSerializer实现为ModelSerializer)。

在序列化程序的create方法中,您将拥有以下内容:

def create(self, validated_data):
    // Groups list has existing groups and new ones as well
    groups = validated_data.pop('groups')

    // Get existing groups by name
    existing_groups = Group.objects.filter(name__in=[g.name for g in groups])
    existing_group_names = [g.name for g in existing_groups]

    // Create new groups
    groups_to_create = []
    for g in groups:
        if g.name not in existing_group_names:
            groups_to_create.append(g)
    Group.objects.bulk_create(groups_to_create)

    // Now that we have all groups, create the user and add the groups to his groups list, updating the M2M relationship
    user = User.objects.create_user(**validated_data)
    user.groups.add(existing_groups + groups_to_create)