Please consider a simple Django app containing a central model called Project. Other resources of this app are always tied to a specific Project.
Exemplary code:
class Project(models.Model):
pass
class Page(models.Model):
project = models.ForeignKey(Project)
I'd like to leverage Django's permission system to set granular permissions per existing project. In the example's case, a user should be able to have a view_page permission for some project instances, and don't have it for others.
In the end, I would like to have a function like has_perm that takes the permission codename and a project as input and returns True if the current user has the permission in the given project.
Is there a way to extend or replace Django's authorization system to achieve something like this?
I could extend the user's Group model to include a link to Project and check both, the group's project and its permissions. But that's not elegant and doesn't allow for assigning permissions to single users.
Somewhat related questions on the Django forum can be found here:
Related StackOverflow questions:
My answer is on the basis of a user should be able to have a view_page permission for one project instance, and don't have it for another instance.
So basically you will have to catch first user visit == first model instance , you can create FirstVisit model which will catch and save each first instance using url, user.id and page.id, then you check if it exists.
# model
class Project(models.Model):
pass
class Page(models.Model):
project = models.ForeignKey(Project)
class FirstVisit(models.Model):
url = models.URLField()
user = models.ForeignKey(User)
page = models.ForeignKey(Page)
#views.py
def my_view(request):
if not FisrtVisit.objects.filter(user=request.user.id, url=request.path, page=request.page.id).exists():
# first time visit == first instance
#your code...
FisrtVisit(user=request.user, url=request.path, page=request.page.id).save()
based on this solution
I suggest to use device (computer or Smartphone) Mac Address instead of url using getmac for maximum first visit check
Orignal answer: Use django-guardian
Edit. As discussed in the comments, I think the django-guardian offers the easiest and cleanest way to achieve this. However, another solution is to create a custom user.
has_perm method in your new user model.from django.db import models
from my_app import Project
class CustomUser(...)
projects = models.ManyToManyField(Project)
def has_perm(self, perm, obj=None):
if isinstance(obj, Project):
if not obj in self.projects.objects.all():
return False
return super().has_perm(perm, obj)