I have a Django model which includes specific permissions. I want to be able to assign permissions to those users in the assigned_to field
. I am using django-guardian
to manage the permissions.
from django.db import models
from django.contrib.auth.models import User
from guardian.shortcuts import assign_perm
class Project(models.Model):
...
assigned_to = models.ManyToManyField(
User, default=None, blank=True, null=True
)
created_by = models.ForeignKey(
User,
related_name="%(app_label)s_%(class)s_related"
)
permissions = (
('view_project', 'View project'),
)
I have tried to implement a custom save method. If I try and do it before the save:
def save(self, *args, **kwargs):
for user in self.assigned_to:
assign_perm('view_project', user, self)
super(Project, self).save(*args, **kwargs)
I get an error:
ObjectNotPersisted: Object <project_name> needs to be persisted first
If I do it after the save (which I guess is wrong anyhow):
def save(self, *args, **kwargs):
super(Project, self).save(*args, **kwargs)
for user in self.assigned_to:
assign_perm('view_project', user, self)
I get an Type Error 'ManyRelatedManager' object is not iterable
.
Should I be using a post-save
signal for this? What is the best approach for what I assume is a common pattern?
The error is caused because the field itself is not iterable, you need to specify the queryset using filter
or all
:
for user in self.assigned_to.all():
assign_perm('view_project', user, self)
However, as you commented, this needs to be done after the parent model instance is saved, so yes you can either create a post_save
signal to accomplish this or save the M2M relations in your view after your call to save
the parent instance.