Django. Разграничить права пользователей по клиентам

Имеем:

Django модель список клиентов (таблица в БД со списком клиентов и другой различной информацией)

Что требуется:

Предоставлять пользователям Django доступ к информации по определённому клиенту\клиентам (права на клиентов мы можем изменять) т.е что бы при авторизации пользователя отображался список клиентов к информации о которых у пользователя есть доступ.

Прошу описать схему как это можно реализовать.


Ответы (3 шт):

Автор решения: Миша

Для начала, как я понял - надо вывести список клиентов, а потом детальное отображение каждого клиента? 2 функции (или класса) со списком клиентов и их детальном отображении. Соответственно, в первой view (список) - будет примерно такой запрос: Model.objects.all() - вывод всех клиентов. Потом детальное отображение: в создании пути, естественно нужен url-параметр, ну у вас это, что угодно, но в качестве примера пусть будет pk - path('list_users/<int:user_id>/',detail,name='detail'). Ну и во view:

def detail(request,user_id):
    user = Model.objects.get(id=user_id)
    ...

Ну и еще нужна проверка доступа. Ну здесь всё просто. К примеру в функции detail(детальное отображение клиентов) сделать проверку: if request.user.(тут пишите либо is_staff или is_authenticated, короче, что вам надо, то и пишите). Или воспользоваться функцией has_pemrs(туда передаете права, которыми должны обладать пользователи). Не знаю поможет ли вам это информация. https://docs.djangoproject.com/en/3.2/ref/contrib/auth/

→ Ссылка
Автор решения: Za Ars

чтобы получить текущего пользователя, достаточно взять его из request.user . передавать id на страницу списка пользователей, доступных для отображения смысла нет. Надо отталкиваться от request.user

Права на клиентов создаете сами, либо через Meta ( https://docs.djangoproject.com/en/3.2/ref/models/options/#permissions ), либо ручками.

Исходя из этих прав, на странице отображения списка пользователей, фильтруете queryset клиентов в зависимости от доступных прав

Нужно больше подробностей? Предоставьте больше информации (где, в админке или нет, как идет разграчением доступа к клиентам)

→ Ссылка
Автор решения: Roman Konoval

То что вам нужно называется ACL - access control list.

В django я бы делал так. Создаем модель, скажем в приложении aclapp:

class ACL(models.Model):
  model_content_type = models.ForeignKey(
       ContentType, on_delete=models.CASCADE)
  object_id = models.CharField(max_length=30)
  username = models.CharField(max_length=30)

Запись в ACL будет означать, что пользователь username имеет доступ к объекту с идентификатором object_id типа описываемого model_content_type.

Теперь нужно модифицировать менеджер, чтоб он учитывал эту таблицу в запросах:

class AclAwareManager(models.Manager):
    def __init__(self, username, model):
       self.username = username
       self.content_type = ContentType.objects.get_for_model(model)

    def get_queryset(self):
        return super().get_queryset().filter(id__in=_get_acl_filter())

    def _get_acl_filter(self)
        return RawSQL("select object_id from aclapp_acl where username = %s and model_conent_type = %s",
            (self.username, self.content_type.id,))

И использовать в модели:

class Client(models.Model):

   name = models.CharField(...)
   ...

   def accessible_objects(self, user):
      return AclAwareManager(user.usename, Client)

Ну и теперь можно использовать менеджер например во view:

def clients_view(request):
   clients = Client.accessible_objects(request.user).filter(name='some name') 

На практике вместо username обычно хранят группу, и смотрят на вхождение пользователя в группу. Так же обычно создают по ACL записи на разный вид действия - т.е. одна запись описывет, кто может читать, вторая - кто может модифицирвать и т.д.

→ Ссылка