I would like to add a extra field to django.contrib.auth.models.Group and to change the display behavior of this field in the django user/groups administration view.
A simple example:
from django.contrib.auth.models import Group
from django.db import models
def _alternative_group_representation(self) -> str:
return self.foo_description or self.name
Group.add_to_class('foo_description',
models.CharField(max_length=150, null=True, blank=True, verbose_name="Human readable name"))
Group.add_to_class('__str__', _alternative_group_representation)
That works if i execute “makemigrations” and “migration” but seems to have real drawbacks:
- the migration are created to venv/lib/python3.8/site-packages/django/contrib/auth/migrations/ and i found no solution to change that
- the migration depends on the version of the django framework
- monkeypatching this class appears to be a unsafe, ugly and dangerous
Is there a better possibility to achieve this?
Proxy models not seem to the right choice to replace the original model.
2 Likes
You are correct. It has been my experience that the standard Django Group model is what it is, and that any change to it implies the creation of a new model.
Rather than trying to modify the Group model itself, you might find it easier to use the “profile model” to associate additional data with the group.
Yes, this does mean that your views and templates need to be aware of that relationship - but then, if you’re creating a new Group-ish model, the views and templates need to be aware of that, too.
1 Like
My main question is: Is there a chance to create a proxied group model and to replace the standard group model by my enhanced version. How can i do this?
To the best of my knowledge, not without replacing the User model as well. If you use a custom user model, you can replace the group field with one having a relationship to your group model.
2 Likes
I am still a newbie regarding the django model internals
If i follow your recommendation and the tutorial at Customizing authentication in Django | Django documentation | Django i am trying something like that:
settings.py
AUTH_USER_MODEL = 'main.FooUser'
# Application definition
INSTALLED_APPS = [
'foo.app.main',
...
main.models.py:
from django.contrib.auth.models import Group
from django.contrib.auth.models import AbstractUser
from django.db import models
class FooGroup(Group):
description = models.CharField(max_length=150, null=True, blank=True, verbose_name="Human readable name")
def __str__(self):
return self.description or self.name
class FooUser(AbstractUser):
# Fetched from the iriginal implementation
groups = models.ManyToManyField(
FooGroup,
verbose_name=('groups'),
blank=True,
help_text=(
'The groups this user belongs to. A user will get all permissions '
'granted to each of their groups.'
),
related_name="user_set",
related_query_name="user",
)
main/admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import FooUser, FooGroup
admin.site.register(FooUser, UserAdmin)
If i now execute a “./manage.py makemigrations” to migrations are created.
What did i missed to use my adapted model?
2 Likes
Is this a new app for which no previous migrations have been created? If so, try manage.py makemigrations main
Migrations relies upon a directory (migrations
) existing within the application. It will not automatically create migrations for an app if that directory doesn’t exist, so the first time you do a makemigrations, you want to specify the name of the app to allow Django to create that directory.
1 Like