#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