Группы на объект с использованием разрешений Django и django-guardian

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

Я хочу пойти на разрешения уровня объекта, и я заметил, что проект django-guardian дал мне именно то, что мне нужно. Он работает с объектами native User и Group, поэтому я пытаюсь найти способ реализовать собственный объект группы в объекте компании.

проблемы, с которыми я сталкиваюсь, это имя в группе уникально. Поэтому, если 2 компании добавят одну и ту же группу, возникнут ошибки.

Я нашел реализацию, которая работает в некотором роде, но кажется мне довольно "хакерской". В моей компании я объявил групповую переменную, которая ссылается на группу:

class Company(models.Model):
    ...
    groups = models.ManyToManyField(Group, through='CompanyRole')

CompanyRole в основном содержит название группы и ссылку на компанию и группу

class CompanyRole(models.Model):
    group = models.ForeignKey(Group)
    company = models.ForeignKey(Company)
    real_name = models.CharField(max_length=60, verbose_name=_('Real name'))

    objects = CompanyGroupManager()

Я создал пользовательский менеджер с удобный способ добавления новой "группы компаний"

class CompanyGroupManager(models.Manager):
    def create_group(self, company, group_name):
        un_group_name = str(company.id) + '#' + group_name
        group = Group.objects.create(name=un_group_name)
        company_group = self.model(
            real_name=group_name, 
            company=company, 
            group=group
        )

        company_group.save(using=self._db)
        return company_group

вот часть, которую я действительно не чувствую себя комфортно. Чтобы изменить проблему с уникальным именем на модели группы, я использовал комбинацию идентификатора компании, хэш-знака и фактического имени группы, чтобы избежать столкновений.

Теперь мой вопрос: есть ли лучшие методы в моем сценарии, я что-то упускаю или это хороший способ выполнить то, что мне нужно?

1 ответов


к сожалению, нет способа обойти уникальное требование, потому что это поле используется в качестве идентификатора: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.unique

ваши варианты следующие:

1) издевательство над моделью.

вы в основном просто создадите новую модель группы, которая не имеет уникального требования. Недостатком здесь является то, что вам нужно использовать его везде, так что если это требуется обновление сторонних приложений, это может не стоить того.

2) сделать имя уникальным. (Как и ты)

убедитесь, что вы хорошо документируете свою конвенцию, чтобы все будущие кодеры знали, на что они смотрят.Что-то вроде "название компании"#"название группы" может иметь более интуитивный смысл, чем идентификатор. Если хэш может появиться в любом из них, используйте более определенный разделитель ("__"- относительно распространенный способ подключения связанных концепций в django, я мог бы пойти на этот.)

Я бы рекомендовал добавить следующее, Чтобы облегчить вам доступ к имени.

def get_name(self):
    # Explain how you get the group name from your uniqueified name
    return self.name.split('#')[1] 

Group.add_to_class('get_name', get_name)

когда вы получаете доступ к имени вашей группы в вашем приложении, просто сделайте:

my_group.get_name()

вы также можете поместить генерирующее uniqueified имя в переопределенную версию save(). Это даст вам лучшее разделение между моделью и видом...