Reputation: 379
I've got the following idea. One user can be in multiple companies. The user has different permissions in every company that he or she is in. The example below doesn't work, because one user would always have the same permissions.
How should I set up my User Model that one User has a different permission in every company?
That's what I've tried so far:
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"
Upvotes: 2
Views: 2093
Reputation: 476604
You define a model for the ManyToManyField
through which the many to many relation flows.
So instead of:
+---------+ M N +-------------+ M N +------------+
| Company |----------| User |----------| Permission |
+---------+ +-------------+ +------------+
| permissions |
+-------------+
We thus write it like:
+---------+ 1 N +-------------+ M 1 +------+
| Company |----------| UserCompany |----------| User |
+---------+ +-------------+ +------+
| M
|
| N
+------------+
| Permission |
+------------+
We can do this with:
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)
You probably want to shift other logic to the through model. For example thehourly_wage
is probably also related to a (User
, Company
)-pair, and not specific to a User
itself.
You can thus add permissions to the UserCompany
with:
someusercompany.permissions.add(some_permission)
Then you check if a UserCompany
has a permission with:
CompanyUser.objects.filter(
user=some_user,
company=some_company,
some_permission=some_permission
).exists()
See more about this in the documentation about through
parameter [django-doc].
Upvotes: 2