如何将"所有者"与默认用户模型相关联



我试图自学Django和Django Rest Framework,但我很难理解对象所有权是如何定义的。

我想使用默认用户模型应用DRF文档中给定的自定义"IsOwnerOrReadOnly"权限。我的目标是:用户将能够在自己的帐户中放置/修补/删除信息,但不能更改任何其他用户的信息。

我的用户序列化程序:

class UserSerializer(serializers.ModelSerializer):
rides = serializers.PrimaryKeyRelatedField(many = True, queryset = Ride.objects.all())
class Meta:
model = User
fields = [
'pk',
'username',
'first_name',
'last_name',
'email',
'password',
'rides'
]
write_only_fields = ['password']
read_only_fields = ['pk', 'username']

IsOwnerOrReadOnly代码:

class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.owner == request.user

线路return obj.owner == request.user出现问题。它总是返回AttributeError: 'User' object has no attribute 'owner’。为什么用户的"所有者"不是用户本身?我如何说"owner=this object"以便我的权限类工作?

后续问题:我想最终扩展默认的User模型,添加更多的字段。如果我通过继承AbstractBaseUser创建了一个新的用户模型,我的权限还会起作用吗?(我刚开始学习Django,所以我不完全确定创建新用户模型的过程是什么。但我认为最好提一下,以防这会改变我定义权限的方式。)

您得到错误是因为没有像所有模型的所有者这样抽象的概念。您必须在模型中定义对象和用户之间的关系,并将其应用于每个模型的权限中。

在这种情况下,你需要确保用户正在尝试修改他自己的用户对象,这样你就可以这样做:

class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj == request.user

因此,从本质上讲,这只适用于User模型,您必须根据模型与用户的关系将其扩展到适用于其他模型。

您可能希望为每个资源定义不同的权限类,而不是试图将所有逻辑放在同一权限类中。

至于您关于扩展用户模型的问题。文档中的这一页解释了扩展现有用户模型的不同方法,基本上是从AbstractUserAbstractbaseUser扩展。Django权限框架在针对这些基类实现时仍然可以工作。

但是请记住,DRF权限类与Django权限不同。您可以使用Django权限在权限类中实现逻辑,但它们可以在没有权限的情况下实现。

根据评论编辑

如果您有一个拥有者的Ride模型,您可以这样做来组合它们。

class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
if isinstance(obj, Ride):
return obj.owner == request.user
return obj == request.user

所有权

假设有一个Model A。要定义所有权,您需要在Model A中创建一个指向User模型的字段。你可以很容易地做到这一点。确保使用django.contrib.auth.get_user_model进行相同操作。

从API获取所属对象的列表

当涉及到获取经过身份验证的用户(request.user)拥有的对象列表时,您正在考虑创建一个过滤器。要做到这一点,有两种方法:

  • 创建一个筛选器类并在其中使用generic views。这更具可扩展性。我在drfaddons.filters.IsOwnerFilterBackend中也做过同样的事情。这是源代码
  • 覆盖每个API类中的def filter_queryset(self, queryset)

确保检索/更新/删除

这一次,您希望确保正在应用权限检查。在这里,您将希望从您正在执行的permissions.BasePermission实现has_object_permissionhas_permission

通常,您需要同时使用filteringpermission检查。

在整个项目中实施

要在整个项目中实现这一点,您需要在settings.pyREST_FRAMEWORK配置中将filterpermission设置为默认值。您还需要确保每个模型中都有一个所有者字段(最好使用相同的名称)。(检查Abstract型号)。

我在我的所有项目中都做了同样的事情,因此,我创建了一个相同的包。检查DRF插件。您也可以通过pip:pip install drfaddons安装它。它将完成上述所有任务。

最新更新