如何在django-rest中使用M2M关系

时间:2013-12-10 17:48:22

标签: django-rest-framework

让我们从django文档中使用的关于M2M关系的模型开始,该模型使用through参数指向将充当中介的模型。

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, 
                                     through='Membership')

    def __unicode__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person)
    group = models.ForeignKey(Group)
    date_joined = models.DateField()

    class Meta:
        ordering = ['date_joined']

现在假设我想为Group模型提供一个休息读写视图,其中还包含每个组内的所有Person,按date_joined字段排序。我想获得的json序列化如下(成员只用他们的id描述):

{
    "id": 1, 
    "name": "U2", 
    "members": [
       20, 
       269, 
       134, 
       12,
    ]
}

我写了一个序列化器:

class GroupSerializer(serializers.ModelSerializer):
    members = serializers.SlugRelatedField(source='membership_set', 
                                           many=True, 
                                           read_only=False,
                                           slug_field='person_id', 
                                           required=True)

    class Meta:
        model = Group
        fields = ('id', 'name', 'members')

虽然对于读取操作它运行良好,但它不适合写入。我应该如何定义序列化器,以便在给定上面定义的序列化的情况下,它将继续:

  1. 创建组对象
  2. 将每个成员添加到组(通过创建成员资格对象)

1 个答案:

答案 0 :(得分:2)

here您可以看到您尝试执行的操作仅适用于读取操作。这是DRF的常见问题,正如其创建者汤姆克里斯蒂在this评论中所述。

此外,对于您想要的JSON序列化,建议使用PK相关字段,如here所示,但这对创建Group对象和添加成员没有帮助。你必须自己编写代码。

希望这有帮助。

修改

通过创建成员身份将每个人添加到群组的代码段:

def post_save(self, obj, created=False):
    # obj represents the Group object
    if created:
        # Test to see if the Group was successfully created
        members = self.request.DATA.get('members', None)
        if members not None:
            for id in members:
                person = Person.objects.get(id=id)
                membership, m_created = Membership.objects.get_or_create(person=person, group=obj)
                # Here you can use m_created to see if the membership already existed and to do whatever else you need.

此实现假定您已使用 auto_now 声明了date_joined。如果没有,您还应该将其作为参数传递。