djangodjango-modelsdjango-permissions

Django Permission per Database Object


I have an architectural question regarding Djangos permission model.

I do have a Database Model which hold companies, and each company can have multiple projects. Users should be able to only see companies that they are assigned to and only see projects which they are assigned to.

I am now confused whether

  1. I should have a Many2Many Relation in the companies and projects which holds the allowed users and then check them on access through the permission system?
  2. Or create a new permission for each company, add this permission to the company and/or project and then give the users these permissions?

Somehow I think solution 1. gets me into problems in the long run when querying all projects one user should see. But solutions 2 got me stuck since there is no permission field in the models, so I always have to cast string field to permission and I will generate a huge amount of permissions overall.

Maybe I am completely overthinking this? What would be the best approach to per Database-Entry permissions?

Thanks and Best Regards


Solution

  • Somehow I think solution 1. gets me into problems in the long run when querying all projects one user should see.

    I don't really see how. If you use Permissions, eventually it will end up in the same modeling, or worse: having to fetch all permissions to determine if you can access a single one.

    A ManyToManyField [Django-doc] is implemented with a junction table [wiki]: a table with (at least) two ForeignKeys: one to the "source" model and one to the "target" model. ForeignKeys have typically an index a structure in the database to filter through tables effectively.

    This means that usually if we want to filter on a specific user id, we can easily get the records we want, without having to go through the entire junction table or Project table.

    We thus can implement this as:

    from django.conf import settings
    
    
    class Project(models.Model):
        # …
        members = models.ManyToManyField(settings.AUTH_USER_MODEL)

    and filter with:

    Project.objects.filter(members=some_user)

    with some_user the user for which we want to see the Projects the user belongs to.