首页 > 解决方案 > Django - 通过合成关系字段的多对多

问题描述

我的应用程序中有这样的模型:

class User(AbstractUser):
    pass


class MyObject(models.Model):
    name = models.CharField(max_length=200, unique=False, db_index=True)

    related_users = models.ManyToManyField(
        User, through='RelatedUsers', related_name='related_users'
    )


class RelatedUsers(models.Model):
    my_object = models.ForeignKey(
        MyObject, related_name='my_object_related_users'
    )
    user = models.ForeignKey(User)
    type = models.CharField(
        max_length=100,
        choices=RelatedUsersTypes.choices()
    )

    class Meta:
        unique_together = ('user', 'my_object', 'type')


class FunctionalityRelatedUsersTypes(BaseChoiceEnum):
    TYPE_1 = 'TYPE 1'
    TYPE_2 = 'TYPE 2'
    TYPE_3 = 'TYPE 3'
    TYPE_4 = 'TYPE 4'
    TYPE_5 = 'TYPE 5'

我想知道是否可以选择在MyObject. 我希望能够使用一个字段按类型获取用户,例如:related_users_type_1. 我也想在 DRF 序列化程序中使用它(所以我可以只传递 id 列表,并且关系将创建一个具有相应类型的代理对象)。

伪代码:

related_users_type_1 = models.RelationField(RelatedUsers, filter={'type': 'TYPE_1'})

我要发送的示例有效负载:

{
    "related_users_type_1": [1, 2, 3],
    "related_users_type_2": [3]
}

预期结果:

标签: pythondjangodjango-rest-framework

解决方案


根据我们的评论,我认为您的问题可以通过以下模型解决:

# just for completeness. should probably use an actual user model
class User (models.Model):
    name = models.CharField(max_length=64)

class MyObject(models.Model):
    name = models.CharField(max_length=64)
    users = models.ManyToMany(User, through='MyObjectUsers', symmetrical=False)

    def add_relations(self, relations):
        for key, list in relations.items():
            for id in list:
                users.add(user=User.objects.get(pk=id), rel_type=key)



class MyObjectUsers(models.Model):
    REL_TYPE_CHOICES=(
        ('TYPE1','TYPE1'),
        ('TYPE2','TYPE2')
    )
    myobject = models.ForeignKey('MyObject', null=True, on_delete=models.SET_NULL)
    user = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
    rel_type = models.CharField(max_length=32, choices = REL_TYPE_CHOICES)

django 文档向您展示了如何遍历关系。

通过上述实现MyObject,您应该能够调用.add_relations({'TYPE1':[1,2,3]})实例MyObject来创建所需的关系。

我在手机上写了这个,所以我真的不知道它是否运行(明天将测试)


推荐阅读