0

免责声明:我是 django 和 django-rules 的新手。

我已经定义了我的模型。该模型有 2 个用户表的外键。创作者和监督者。实例应可由员工、创建者或主管更改/更新。

我为 is_creator 和 is_supervisor 定义了谓词并制定了规则:

@rules.predicate
def is_creator(user, mymodel):
    return mymodel.creator == user

@rules.predicate
def is_supervisor(user, mymodel):
    return mymodel.supervisor == user

can_edit = is_supervisor | is_creator | rules.is_staff

在模型元类中我添加了:

rules_permissions = {           
    'change': can_edit
}

在我看来,然后我想显示一个编辑按钮,该按钮链接到基于这些权限的编辑表单。

{% block content %}
{% has_perm 'mymodel.change_mymodel' user instance as can_edit %}
{% if can_edit %}
<button type="button" class="btn btn-warning"><h6>Edit</h6></button>
{% endif %}
{% endblock %}

当我以超级用户身份登录时,该按钮按预期显示。当我使用应该能够编辑特定实例的测试用户时,根本不显示该按钮。因此,进行了某些检查,但未按预期进行。

我为索引页面提供了第二个类似的功能。仅显示用户有权执行的操作。同样,超级用户可以看到所有内容,但测试用户却看不到。

在这种情况下,我有以下谓词,它在不同的模型上用作“添加”权限:

@rules.predicate
def can_add_xyz(user):
    return rules.is_staff | rules.is_group_member("Add_XYZ")

在这两种情况下,除了 is_staff 之外的所有检查似乎都失败了。我究竟做错了什么?

4

1 回答 1

0

有两个问题正在发生。首先 RTFM 并正确执行:

在我的模板中,我使用has_perm entity_name.add_entity_name而不是按照文档中正确描述的方式使用has_perm myapp.add_entity_name

在修复了谓词之后,现在实际上被调用了,我可以调试它们。一个更大的问题暴露了出来。我能够修复它,但不喜欢修复。

谓词:

@rules.predicate
def is_creator(user, mymodel):
    return mymodel.creator == user

问题是在我检查此权限的模板中,mymodel 是由嵌套的 django-rest-framework 序列化程序生成的相关实体。这意味着模板中使用的实例然后提交给这个谓词不是 mymodel 实例而是 OrderedDict ,因此我得到一个异常OrderedDict has no attribute 'creator'.

另一个问题是创建者不是直接的 Django auth_user,而是 OneToOne 扩展用户。所以 mymodel.creator == user永远不会是真的。

@rules.predicate
def is_creator(user, mymodel):
    #if called from template as related entity,
    #mymodel is an OrderedDict from a serializer
    if isinstance(mymodel, collections.OrderedDict):        
        return mymodel["creator"] == user.userprofile.pk
    return mymodel.creator == user.userprofile

这解决了问题,现在显示了正确的内容,但我对此并不完全满意(类型检查)。因此,仍然欢迎任何使这一点变得更好的建议。

于 2020-04-03T05:49:51.917 回答