Как настроить права пользователя django для одного пользователя с несколькими разрешениями?
У меня есть следующая идея. Один пользователь может быть в нескольких компаниях. Пользователь имеет разные разрешения в каждой компании, в которой он находится. Пример ниже не работает, потому что один пользователь всегда будет иметь одинаковые разрешения.
Как мне настроить мою модель пользователя, чтобы один пользователь имел разные разрешения в каждой компании?
Вот что я пробовал до сих пор:
class User(AbstractUser):
hourly_wage = models.DecimalField(decimal_places=2, max_digits=6, default=8.50)
class Meta:
permissions = (("is_general", "Can add people to his company and see everything"),
("is_captain", "Can add/edit/delete everything"),
("is_staff", "Can add/edit/delete jobs"),
("is_programmer", "Can do what he or she wants to do"))
def clean(self):
self.username = self.username.lower()
class Company(models.Model):
name = models.CharField(max_length=80)
slug = models.SlugField(unique=True)
users = models.ManyToManyField(User, related_name="companies")
class Meta:
verbose_name_plural = "companies"
1 ответ
Вы определяете модель для ManyToManyField
через которые течет отношение многие ко многим.
Так что вместо:
+---------+ M N +-------------+ M N +------------+
| Company |----------| User |----------| Permission |
+---------+ +-------------+ +------------+
| permissions |
+-------------+
Таким образом, мы пишем это так:
+---------+ 1 N +-------------+ M 1 +------+
| Company |----------| UserCompany |----------| User |
+---------+ +-------------+ +------+
| M
|
| N
+------------+
| Permission |
+------------+
Мы можем сделать это с:
from django.contrib.auth.models import Permission
class User(AbstractUser):
def clean(self):
self.username = self.username.lower()
class Company(models.Model):
name = models.CharField(max_length=80)
slug = models.SlugField(unique=True)
users = models.ManyToManyField(User, through='app.CompanyUser', related_name="companies")
class Meta:
verbose_name_plural = "companies"
class CompanyUser(models.Model):
user = models.ForeignKey('app.User', on_delete=models.CASCADE)
company = models.ForeignKey('app.Company', on_delete=models.CASCADE)
hourly_wage = models.DecimalField(decimal_places=2, max_digits=6, default=8.50)
permissions = models.ManyToManyField(Permission, on_delete=models.CASCADE)
Возможно, вы захотите перенести другую логику в сквозную модель. Например, hourly_wage
вероятно также связано с (User
, Company
) -парой, а не специфичной для User
сам.
Таким образом, вы можете добавить разрешения для UserCompany
с:
someusercompany.permissions.add(some_permission)
Затем вы проверите, если UserCompany
имеет разрешение с:
CompanyUser.objects.filter(
user=some_user,
company=some_company,
some_permission=some_permission
).exists()
Подробнее об этом см. В документации о through
параметр [django-doc].