How do I extend the Django Group model?


Is there a way to extend the built-in Django Group object to add additional attributes similar to the way you can extend a user object? With a user object, you can do the following:

class UserProfile(models.Model):
    user = models.OneToOneField(User)

and add the following to the file

AUTH_PROFILE_MODULE = 'app.UserProfile'

which gets you:

profile = User.objects.get(id=1).get_profile()

Is there any equivalent to this approach for extending a group? If not, is there an alternative approach I can take?

12/19/2015 9:38:35 AM

Accepted Answer

You can create a model that subclasses Group, add your own fields, and use a Model Manager to return any custom querysets you need. Here's a truncated example showing how I extended Group to represent Families associated with a school:

from django.contrib.auth.models import Group, User

class FamilyManager(models.Manager):
    Lets us do querysets limited to families that have 
    currently enrolled students, e.g.:
    def get_query_set(self):
        return super(FamilyManager, self).get_query_set().filter(student__enrolled=True).distinct()

class Family(Group):
    notes = models.TextField(blank=True)

    # Two managers for this model - the first is default 
    # (so all families appear in the admin).
    # The second is only invoked when we call 
    # Family.has_students.all()  
    objects = models.Manager()
    has_students = FamilyManager()

    class Meta:
        verbose_name_plural = "Families"
        ordering = ['name']

    def __unicode__(self):
10/12/2017 11:05:11 PM

If you simply subclass the Group object then by default it will create a new database table and the admin site won't pick up any new fields.

You need to inject new fields into the existing Group:

if not hasattr(Group, 'parent'):
    field = models.ForeignKey(Group, blank=True, null=True, related_name='children')
    field.contribute_to_class(Group, 'parent')

To add methods to the Group, subclass but tag the model as proxy:

class MyGroup(Group):

    class Meta:
        proxy = True

    def myFunction(self):
        return True

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow