Создание пользовательских разрешений на доступ к форме / проверка в django admin

#python #django #authentication #permissions #django-admin

#python #django #аутентификация #разрешения #django-admin

Вопрос:

Я использую модель «Задачи» для создания операций / административных задач на моей панели мониторинга. У каждой задачи есть назначенный и проверяющий. Назначенный завершает задачу, проходя несколько проверок, и рецензент проверяет их работу, оба из них требуют, чтобы каждый пользователь редактировал проверку, но ни один пользователь не должен иметь доступа или изменять результат другого.

Если назначенный пользователь просматривает задачу (со встроенными проверками), он должен иметь возможность изменять только элементы «результат» и «комментарий» проверки, где рецензент может редактировать только элементы «review_result» и «reviewer_comment».

Для проверки этого мне нужно использовать тот факт, что при заданном a check текущий пользователь, редактирующий страницу, равен check.task.assignee или check.task.reviewer .

Я не могу найти простой способ сделать это, даже используя django-guardian, поскольку для этого требуются разрешения на уровне полей, а не на уровне объекта. Я рассматривал возможность использования проверки ModelForm, но не могу найти способ получить доступ к пользователю из модели с помощью некоторых хаков, таких как django-cuser.

Существует ли другая архитектура, которая позволила бы это? Единственный путь, который я вижу, — это использовать django-guardian в сочетании с двумя проверками, проверкой и проверкой, и устанавливать разрешения на уровне объекта при выборе правопреемника и рецензента.

 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:

Правильный метод для достижения этой цели — переопределить get_readonly_fields метод InlineModelAdmin (в вашем встроенном классе).

 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