Как мне расширить модель Django Group? - PullRequest
39 голосов
/ 02 февраля 2010

Есть ли способ расширить встроенный объект Django Group, чтобы добавить дополнительные атрибуты, аналогичные способу расширения пользовательского объекта? С пользовательским объектом вы можете сделать следующее:

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

и добавьте следующее в файл settings.py

AUTH_PROFILE_MODULE = 'app.UserProfile'

, который получает вас:

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

Существует ли какой-либо эквивалент этого подхода для расширения группы? Если нет, могу ли я выбрать альтернативный подход?

Ответы [ 3 ]

43 голосов
/ 06 октября 2011

Если вы просто создадите подкласс объекта Group, то по умолчанию он создаст новую таблицу базы данных, и сайт администратора не получит новые поля.

Вам необходимо добавить новые поля в существующую группу:

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

Чтобы добавить методы в группу, создайте подкласс, но пометьте модель как прокси:

class MyGroup(Group):

    class Meta:
        proxy = True

    def myFunction(self):
        return True
24 голосов
/ 02 февраля 2010

Вы можете создать модель, которая подклассирует Группу, добавить свои собственные поля и использовать Менеджер моделей для возврата любых пользовательских наборов запросов, которые вам нужны. Вот усеченный пример, показывающий, как я расширил группу для представления семей, связанных со школой:

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.:
        Family.has_students.all() 
    """
    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):
        return self.name
4 голосов
/ 27 августа 2018

Для меня сработало решение на основе:

https://docs.djangoproject.com/pl/1.11/topics/auth/customizing/#extending-user

Позвольте мне объяснить, что я сделал с группами, расширяющими модель по умолчанию псевдонимом электронной почты:

Прежде всего я создал собственное приложение django, назовите его

python manage.py startapp auth_custom

Кодовый раздел:

В auth_custom / models.py Я создал объект CustomGroup

from django.contrib.auth.models import Group
from django.db import models

class CustomGroup(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="")

В auth_custom / admin.py :

from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.models import Group


class GroupInline(admin.StackedInline):
    model = CustomGroup
    can_delete = False
    verbose_name_plural = 'custom groups'


class GroupAdmin(BaseGroupAdmin):
    inlines = (GroupInline, )


# Re-register GroupAdmin
admin.site.unregister(Group)
admin.site.register(Group, GroupAdmin)

После выполнения миграций у меня есть такой результат в представлении администратора Django.

Пользовательская группа в Django Admin

Чтобы получить доступ к этому настраиваемому полю, вы должны набрать:

from django.contrib.auth.models import Group


    group = Group.objects.get(name="Admins")  # example name

    email_alias = group.customgroup.email_alias

Если есть какие-либо ошибки, пожалуйста, сообщите мне, я исправлю этот ответ.

...