Note that there are some explanatory texts on larger screens.

plurals
  1. POdjango guardian, permissions and extending django auth groups to 'organization' models
    primarykey
    data
    text
    <p>django guardian <a href="https://github.com/lukaszb/django-guardian" rel="noreferrer">https://github.com/lukaszb/django-guardian</a> is a really well written object-level permissions app; and I have actually read up on and used quite a number of other django object level permissions app in various django projects.</p> <p>In a recent project that I am working on, I decided to use django guardian but I have a model design question relating to the <strong>pros and cons of two possible approaches</strong> and their respective implications on sql query performance:-</p> <ol> <li><p>using <code>django.contrib.auth.models.Group</code> and extending that to my custom organization app's models; or</p></li> <li><p>using <code>django.contrib.auth.models.User</code> instead and creating an m2m field for each of the organization type in my organization app. </p></li> </ol> <p><strong>Approach #1</strong></p> <pre><code># Organisation app's models.py from django.contrib.auth.models import Group class StudentClass(models.Model): name = models.CharField('Class Name', max_length=255) groups = models.ManyToManyField(Group, blank=True) size = models.IntegerField('Class Size', blank=True) class SpecialInterestGroup(models.Model): name = models.CharField('Interest Group Name', max_length=255) groups = models.ManyToManyField(Group, blank=True) description = models.TextField('What our group does!', blank=True) class TeachingTeam(models.Model): name = models.CharField('Teacher Team Name', max_length=255) groups = models.ManyToManyField(Group, blank=True) specialization = models.TextField('Specialty subject matter', blank=True) </code></pre> <p>In this approach, when a user is added to a group (django group) for the first time, the group object is created and also assigned to one of these 3 classes, if that group object does not yet belong to the class it is added into.</p> <p>This means that each StudentClass object, <code>sc_A</code>, <code>sc_B</code> etc, can possibly contain a lot of groups.</p> <p>What that means is that for me to ascertain whether or not a specific user (say <code>myuser</code>) belongs to a particular organization, I have to query for all the groups that the user belong to, via <code>groups_myuser_belongto = myuser.groups</code> and then query for all the groups that are associated to the organization I am interested in, via <code>groups_studentclass = sc_A.groups.all()</code> and since I now have 2 lists that I need to compare, I can do <code>set(groups_myuser_belongto) &amp;&amp; set(groups_studentclass)</code>, which will return a new set which may contain 1 or more groups that intersect. If there are 1 or more groups, <code>myuser</code> is indeed a member of <code>sc_A</code>.</p> <p>This model design therefore implies that I have to go through a lot of trouble (and extra queries) just to find out if a user belongs to an organization.</p> <p>And the reason why I am using m2m to groups is so as to make use of the Group level permissions functionality that django guardian provides for.</p> <p>Is such a model design practical?</p> <p>Or am I better off going with a different model design like that...</p> <p><strong>Approach #2</strong></p> <pre><code># Organisation app's models.py from django.contrib.auth.models import User class StudentClass(models.Model): name = models.CharField('Class Name', max_length=255) users = models.ManyToManyField(User, blank=True) size = models.IntegerField('Class Size', blank=True) class SpecialInterestGroup(models.Model): name = models.CharField('Interest Group Name', max_length=255) users = models.ManyToManyField(User, blank=True) description = models.TextField('What our group does!', blank=True) class TeachingTeam(models.Model): name = models.CharField('Teacher Team Name', max_length=255) users = models.ManyToManyField(User, blank=True) specialization = models.TextField('Specialty subject matter', blank=True) </code></pre> <p>Obviously, this model design makes it really easy for me to check if a user object belongs to a particular organization or not. All I need to do to find out if user <code>john</code> is part of a TeachingTeam <code>maths_teachers</code> or not is to check:</p> <pre><code>user = User.objects.get(username='john') maths_teachers = TeachingTeam.objects.get(name='Maths teachers') if user in maths_teachers.users.all(): print "Yes, this user is in the Maths teachers organization!" </code></pre> <p>But what this model design implies is that <em>when I add a user object to a group</em> (recall that I want to use django guardian's Group permissions functionality), I have to make sure that the <code>save()</code> call adds the user object into a "Maths Teachers" group in <code>django.contrib.auth.models.Group</code> <strong>AND</strong> into my custom <code>TeachingTeam</code> class's "Maths Teachers" object. And that doesn't feel very DRY, not to mention that I have to somehow ensure that the save calls into both the models are done in a single <code>transaction</code>.</p> <p>Is there a better way to design my models given this use case/requirement - use django groups and yet provide a way to "extend" the django's native group functionality (almost like how we extend django's user model with a "user profile app")?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload