在Django REST Framework中实现角色权限预选(显示名称)并正确处理多对多关系的增改操作
在Django REST Framework中实现角色权限预选(显示名称)并正确处理多对多关系的增改操作
我正在用Django和Django Rest Framework实现基于角色的访问控制(RBAC)。我想通过DRF的可浏览API创建一个带有一组权限的角色,同时需要更新这些权限的功能——包括添加新权限和移除现有权限。在可浏览API中显示角色时,我希望关联的权限是预选状态以便清晰查看,同时还要显示所有其他可用权限方便添加。
我目前的实现
模型代码
这里是我简化后的模型:
class BaseModel(models.Model): pkid = models.BigAutoField(primary_key=True, editable=False) id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) is_active = models.BooleanField(default=True) class Meta: abstract = True class Role(BaseModel): name = models.CharField(max_length=100) class Permission(BaseModel): name = models.CharField(max_length=100, unique=True) description = models.TextField(null=True, blank=True) class RolePermission(BaseModel): role = models.ForeignKey( Role, on_delete=models.CASCADE, related_name="role_permissions" ) permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
最初的序列化器
class RoleSerializer(serializers.ModelSerializer): permissions = serializers.SlugRelatedField( queryset=Permission.objects.all(), many=True, required=False, slug_field="name" ) business = serializers.PrimaryKeyRelatedField( queryset=Business.objects.all(), required=False, allow_null=True ) class Meta: model = Role fields = ("id", "name", "is_default", "permissions", "business") def to_representation(self, instance): representation = super().to_representation(instance) permissions = instance.role_permissions.all().values_list( "permission__name", flat=True ) representation["permissions"] = list(permissions) return representation def to_internal_value(self, data): data = data.copy() permissions_data = data.pop("permissions", []) permissions_qs = Permission.objects.filter(name__in=permissions_data) data["permissions"] = [permission.id for permission in permissions_qs] return super().to_internal_value(data)
遇到的问题
当我发送更新请求修改权限时,会收到如下错误:
{ "permissions": [ "Object with name=[UUID('e4ac49c0-093a-4281-96b0-0846917fc62b')] does not exist." ] }
修改后的序列化器
我重写了序列化器来修复这个错误:
class RoleSerializer(serializers.ModelSerializer): permissions = serializers.PrimaryKeyRelatedField( queryset=Permission.objects.all(), many=True, required=False ) business = serializers.PrimaryKeyRelatedField( queryset=Business.objects.all(), required=False, allow_null=True ) class Meta: model = Role fields = ("id", "name", "is_default", "permissions", "business") def to_representation(self, instance): representation = super().to_representation(instance) permissions = instance.role_permissions.all().values_list( "permission", flat=True ) representation["permissions"] = list(permissions) return representation def to_internal_value(self, data): data = data.copy() permissions_data = data.pop("permissions", []) internal_value = super().to_internal_value(data) internal_value["permissions"] = permissions_data return internal_value
但这样修改后,返回的JSON里权限变成了ID而不是名称:
{ "id": "0b3de100-82ef-4a02-b94e-659cb6dd4314", "name": "neweee", "is_default": false, "business": null, "permissions": [ 1, 2 ] }
我的问题
如何在DRF可浏览API中正确地将关联字段(权限)以名称形式预选,同时还能无错误地进行创建/更新操作?
谢谢!
备注:内容来源于stack exchange,提问作者nabroleonx
相关产品推荐
相关产品推荐

