在Django管理中创建用户特定的表单访问权限/验证

时间:2019-04-17 10:24:28

标签: python django authentication permissions django-admin

我正在使用“任务”模型在仪表板上创建操作/管理任务。每个任务都有一个受让人和一个审阅者。受理人通过几次检查来完成任务,审阅者验证他们的工作,这两项工作都需要每个用户编辑检查,但是任何一个用户都不能访问或修改对方的结果。

如果受让人查看任务(带有内联检查),则他们只能修改检查的“结果”和“评论”元素,因为审阅者只能编辑“ review_result”和“ reviewer_comment”元素。

要验证这一点,我需要使用以下事实:给定check,当前编辑页面的用户等于check.task.assigneecheck.task.reviewer

即使使用django-guardian,我也找不到简单的方法来执行此操作,因为这需要字段级权限,而不是对象级权限。我考虑过使用modelForm验证,但是找不到通过django-cuser之类的黑客从模型内部访问用户的方法。

是否有另一种架构可以做到这一点?我能看到的唯一前进的方法是将django-guardian与两个检查(一个检查和一个checkReview)结合使用,并设置对象级别权限,以选择受让人和审阅者。

class Task(PolymorphicModel):
    date_created = models.DateTimeField(auto_created=True)
    date_accepted = models.DateTimeField(null=True)
    date_reviewed = models.DateTimeField(null=True)
    date_closed = models.DateTimeField(null=True)
    state = FSMField(default="open")

    assignee = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=True,
        related_name="assigned_tasks",
        related_query_name="assigned_task",
    )
    reviewer = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=True,
        related_name="review_tasks",
        related_query_name="review_task",
    )

class Check(PolymorphicModel):
    result = models.BooleanField(null=True)
    comment = models.CharField(max_length=500, null=True, blank=True)
    review_result = models.BooleanField(null=True)
    reviewer_comment = models.CharField(max_length=500, null=True)
    task = models.ForeignKey(Task, on_delete=models.CASCADE)

1 个答案:

答案 0 :(得分:0)

实现此目标的正确方法是重写InlineModelAdmin的get_readonly_fields方法(在您的Inline类中)。

def get_readonly_fields(self, request, obj=None):
    if obj is None:
        logger.error("An admin has created a check from the dashboard (this should not happen)!")
        return []
    user = request.user
    fields = [field.name for field in self.opts.local_fields]
    if user == obj.assignee:
        fields.remove(['result', 'comment'])
    elif user == obj.reviewer:
        fields.remove(['review_result', 'reviewer_comment'])
    return fields