How Do I Extend The Django Group Model?
Solution 1:
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:
classMyGroup(Group):
classMeta:
proxy = TruedefmyFunction(self):
returnTrue
Solution 2:
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
classFamilyManager(models.Manager):
"""
Lets us do querysets limited to families that have
currently enrolled students, e.g.:
Family.has_students.all()
"""defget_query_set(self):
returnsuper(FamilyManager, self).get_query_set().filter(student__enrolled=True).distinct()
classFamily(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()
classMeta:
verbose_name_plural = "Families"
ordering = ['name']
def__unicode__(self):
return self.name
Solution 3:
For me worked solution based on:
https://docs.djangoproject.com/pl/1.11/topics/auth/customizing/#extending-user
Let me explain what I did with Groups extending default model with email alias:
First of all I created my own django application let name it
python manage.py startapp auth_custom
Code section:
In auth_custom/models.py I created object CustomGroup
from django.contrib.auth.models import Group
from django.db import models
classCustomGroup(models.Model):
"""
Overwrites original Django Group.
"""def__str__(self):
return"{}".format(self.group.name)
group = models.OneToOneField('auth.Group', unique=True)
email_alias = models.EmailField(max_length=70, blank=True, default="")
In auth_custom/admin.py:
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.models import Group
classGroupInline(admin.StackedInline):
model = CustomGroup
can_delete = False
verbose_name_plural = 'custom groups'classGroupAdmin(BaseGroupAdmin):
inlines = (GroupInline, )
# Re-register GroupAdmin
admin.site.unregister(Group)
admin.site.register(Group, GroupAdmin)
After making migrations I have such result in Django Admin view.
In order to access this custom field you must type:
from django.contrib.auth.models import Groupgroup = Group.objects.get(name="Admins") # example name
email_alias = group.customgroup.email_alias
If any mistakes please notify me, I'll correct this answere.
Solution 4:
I managed to use migrations with @Semprini aswer.
So i needed to create a company related field in my groups related field, so in my models i did this:
ifnot hasattr(Group, 'company'):
field = models.ForeignKey(Company, on_delete=models.DO_NOTHING, null=True)
field.contribute_to_class(Group, 'company')classGroup(Group):
class Meta:
proxy = True
Then i run manage.py makemigrations. This created 2 files. One with dependencies on the other, but the first one belonging to the auth
app was created inside my virtual enviroment. The files look like this:
# Generated by Django 2.2.5 on 2019-10-08 16:00from django.db import migrations, models
import django.db.models.deletion
classMigration(migrations.Migration):
dependencies = [
('myapp', '0013_guestuser_permissions_20190919_1715'),
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.AddField(
model_name='group',
name='company',
field=models.ForeignKey(
null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='myapp.Company'),
),
]
The second one created in myapp migrations folder look like this:
# Generated by Django 2.2.5 on 2019-10-08 16:00import django.contrib.auth.models
from django.db import migrations
classMigration(migrations.Migration):
dependencies = [
('auth', '0012_group_company_20191008'),
('myapp', '0013_guestuser_permissions_20190919_1715'),
]
operations = [
migrations.CreateModel(
name='Group',
fields=[
],
options={
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('auth.group',),
managers=[
('objects', django.contrib.auth.models.GroupManager()),
],
),
]
So the solution was to move the file created in my virtualenv to myapp migrations folder, before the other one generated with makemigrations, but since the migration is applied to the auth
app instead of myapp
i have to implement a workaround in the file. So the final file now is:
# Generated by Django 2.2.5 on 2019-10-08 16:00from django.db import migrations, models
import django.db.models.deletion
classMigration(migrations.Migration):
dependencies = [
('myapp', '0013_guestuser_permissions_20190919_1715'),
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.AddField(
model_name='group',
name='company',
field=models.ForeignKey(
null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='myapp.Company'),
),
]
defmutate_state(self, project_state, preserve=True):
"""
This is a workaround that allows to store ``auth``
migration outside the directory it should be stored.
"""
app_label = self.app_label
self.app_label = 'auth'
state = super(Migration, self).mutate_state(project_state, preserve)
self.app_label = app_label
return state
defapply(self, project_state, schema_editor, collect_sql=False):
"""
Same workaround as described in ``mutate_state`` method.
"""
app_label = self.app_label
self.app_label = 'auth'
state = super(Migration, self).apply(project_state, schema_editor, collect_sql)
self.app_label = app_label
return state
The mutate an apply methods allow you to migrate to the auth
app from myapp
migrations.
In the second file i just change the dependencie to depend on the newly file created:
# Generated by Django 2.2.5 on 2019-10-08 16:00import django.contrib.auth.models
from django.db import migrations
classMigration(migrations.Migration):
dependencies = [
('myapp', '0014_group_company_20191008'),
('myapp', '0013_guestuser_permissions_20190919_1715'),
]
operations = [
migrations.CreateModel(
name='Group',
fields=[
],
options={
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('auth.group',),
managers=[
('objects', django.contrib.auth.models.GroupManager()),
],
),
]
Post a Comment for "How Do I Extend The Django Group Model?"