【问题标题】:How to work with M2M relationship in django-rest如何在 django-rest 中处理 M2M 关系
【发布时间】:2013-12-10 17:48:22
【问题描述】:

让我们从 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 模型保留一个 read-write 视图,该视图还包含每个组内的所有 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. 将每个成员添加到组(通过创建成员资格对象)

【问题讨论】:

    标签: django-rest-framework


    【解决方案1】:

    here 可以看出,您尝试执行的操作仅适用于读取操作。这是 DRF 的一个常见问题,正如其创建者 Tom Christie 在 this 评论中所述。

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

    希望这会有所帮助。

    编辑

    通过创建成员资格将每个人添加到组的代码 sn-p:

    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。如果没有,您也应该将其作为参数传递。

    【讨论】:

    • 感谢您给我的明确回答,以及文档相关部分的链接或作者在这一点上的回答。很遗憾,我试图做的事情并没有得到框架的大力支持。您能否建议我自己编写代码来完成任务?什么是正确的方法?再次感谢您!
    • 很高兴能帮上忙 :) 至于创建部分,您可以在两个地方进行:在 post/create 方法中或在 post_save 方法。我建议在 post_save 中完成,因为这意味着您允许框架创建 Group 对象,剩下要做的就是添加成员。我将用一个小代码 sn-p 来编辑我的答案,以了解如何使用此方法。
    • 非常感谢,非常感谢您的支持!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 2021-04-21
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多