更新与 REST 的多对多关联

Posted

技术标签:

【中文标题】更新与 REST 的多对多关联【英文标题】:Updating many-to-many association with REST 【发布时间】:2016-09-18 14:33:19 【问题描述】:

我有三个不同的模型,UserPermissionSetPermission。这些模型分别代表它们的 SQL 表。

User 具有多对一关联 PermissionSet,用户可能有一个 PermissionSet 或没有。 PermissionSets 将不属于任何一个或多个Users。

PermissionSetPermissions 具有多对多关联。一个Permission 可以由多个PermissionSets 拥有或不拥有,其中PermissionSets 可以拥有多个Permissions 或根本不拥有。

所以我创建了四个表:userspermission_setspermissions 和一个联结表 permission_sets_permissions

我需要保留在UserPermissionSet 中所做的更改。这由一个名为 PermissionSetGrant 的模型处理,它有自己的表 permission_set_grants

使用基于 HTTP 和 JSON 的 RESTful API 更改 PermissionSetPermissions 的最佳方法是什么?

例如,用这样的请求修改PermissionSet是不是一个好方法:

PUT /api/v1/permission_sets/7

//  Payload

    "permission_set": 
        //  Assume these properties of the entity aren't changed
        "name": "default",
        "description": "Default permission set.",

        //  Here we're changing the permissions
        "permission_ids": [
            24,
            27,
            35
        ]
    


-> 200 OK

还是使用额外的 REST 路径添加权限?

POST /api/v1/permission_sets/7/permissions

//  Payload

    "permission": 24


-> 201 CREATED

以及何时需要删除该权限

DELETE /api/v1/permission_sets/7/permissions/24

-> 203 ACCEPTED

我还要补充一点,从客户端的角度来看,请求是幂等的和确定的。权限数至少为 100。因此,批处理操作将在第二种方法中执行。

【问题讨论】:

【参考方案1】:

我认为您当前的解决方案还可以。如果您只想将权限与权限集联系起来,那么您可以使用多个 id 来描述集合,而不是使用相同的有效负载,例如

PUT /api/v1/permission_sets/1+2+3/permissions/4+5+6/
DELETE /api/v1/permission_sets/1+2+3/permissions/4+5+6/

如果我是你,我不会拘泥于分层 URI 设计,但大多数时候它很不方便。

PUT /api/v1/permissions/4+5+6/into/permission/sets/1+2+3/
DELETE /api/v1/permissions/4+5+6/from/permission/sets/1+2+3/

请注意,URI 设计没有 REST 约束,因为 REST operates with hyperlinks 和机器客户端。因此,从客户端的角度来看,URI 的结构并不重要,只要它可以用 URI 模板描述即可。唯一需要记住的是,URI 和资源之间存在 n:1 关系,因此多个 URI 可以识别同一个资源,但单个 URI 不能识别多个资源。

【讨论】:

【参考方案2】:

如果您要允许一次更新如此大量的权限,那么PATCH 可能是您的朋友:

查看RFC 6902(定义补丁标准),从客户端的角度来看,API 可以这样调用

PATCH /api/v1/permission_sets/7
[
     "op": "add", "path": "/permission_ids", "value": [ "24", "27", "35" ]
]

但是,不幸的是,PATCH 不是 idempotent 方法(POST 也不是,原因几乎相同),因此排除后您只剩下 PUT,这很好,只是比PATCH 更详细一点(客户端必须PUT 整个对象,包括整个permission_ids 集合)。

【讨论】:

以上是关于更新与 REST 的多对多关联的主要内容,如果未能解决你的问题,请参考以下文章

与关联对象在同一张表上的多对多关系

SQLAlchemy 使用关联配置与自我的多对多关系

完全迷失:在 Django Rest 框架中使用序列化器和更新的多对多

Hibernate的多对多关联关系

如何删除与隐藏交集表的多对多关联中的记录?

与 Shopware 6 中的其他字段的多对多关联