Джанго стражhttps://github.com/lukaszb/django-guardianэто действительно хорошо написанное приложение с разрешениями уровня объекта -; и я на самом деле прочитал и использовал довольно много других приложений разрешений на уровне объекта django в различных проектах django.
В недавнем проекте, над которым я работаю, я решил использовать django guardian, но у меня есть вопрос о дизайне модели, касающийся плюсов и минусов двух возможных подходов и их соответствующих последствий для производительности sql-запросов:-
используя django.contrib.auth.models.Group
и распространяя это на модели моего пользовательского приложения организации; или
используя вместо этого django.contrib.auth.models.User
и создавая поле m2m для каждого типа организации в приложении моей организации.
Подход #1
# Organisation app's models.py
from django.contrib.auth.models import Group
class StudentClass(models.Model):
name = models.CharField('Class Name', max_length=255)
groups = models.ManyToManyField(Group, blank=True)
size = models.IntegerField('Class Size', blank=True)
class SpecialInterestGroup(models.Model):
name = models.CharField('Interest Group Name', max_length=255)
groups = models.ManyToManyField(Group, blank=True)
description = models.TextField('What our group does!', blank=True)
class TeachingTeam(models.Model):
name = models.CharField('Teacher Team Name', max_length=255)
groups = models.ManyToManyField(Group, blank=True)
specialization = models.TextField('Specialty subject matter', blank=True)
При таком подходе, когда пользователь впервые добавляется в группу (django group ), объект группы создается и также назначается одному из этих трех классов:если этот групповой объект еще не принадлежит классу, в который он добавлен.
Это означает, что каждый объект StudentClass, sc_A
, sc_B
и т. д., может содержать множество групп.
Это означает, что мне нужно выяснить, говорит ли конкретный пользователь (myuser
)принадлежит определенной организации, я должен запросить все группы, к которым принадлежит пользователь, через groups_myuser_belongto = myuser.groups
, а затем запросить все группы, связанные с интересующей меня организацией, через groups_studentclass = sc_A.groups.all()
, и поскольку я теперь есть 2 списка, которые мне нужно сравнить, я могу сделать set(groups_myuser_belongto) && set(groups_studentclass)
, который вернет новый набор, который может содержать 1 или более пересекающихся групп. Если есть 1 или более групп, myuser
действительно является членом sc_A
.
Таким образом, эта модель модели подразумевает, что мне придется пройти через множество проблем (и дополнительных запросов ), чтобы узнать, принадлежит ли пользователь организации.
И причина, по которой я использую m2m для групп, заключается в том, чтобы использовать функциональность разрешений на уровне группы, которую предоставляет django guardian.
Практичен ли такой дизайн модели?
Или мне лучше пойти с другим дизайном модели, как этот...
Подход #2
# Organisation app's models.py
from django.contrib.auth.models import User
class StudentClass(models.Model):
name = models.CharField('Class Name', max_length=255)
users = models.ManyToManyField(User, blank=True)
size = models.IntegerField('Class Size', blank=True)
class SpecialInterestGroup(models.Model):
name = models.CharField('Interest Group Name', max_length=255)
users = models.ManyToManyField(User, blank=True)
description = models.TextField('What our group does!', blank=True)
class TeachingTeam(models.Model):
name = models.CharField('Teacher Team Name', max_length=255)
users = models.ManyToManyField(User, blank=True)
specialization = models.TextField('Specialty subject matter', blank=True)
Очевидно, что такой дизайн модели позволяет мне очень легко проверить, принадлежит ли пользовательский объект определенной организации или нет. Все, что мне нужно сделать, чтобы узнать, является ли пользователь john
частью TeachingTeam maths_teachers
или нет, это проверить:
user = User.objects.get(username='john')
maths_teachers = TeachingTeam.objects.get(name='Maths teachers')
if user in maths_teachers.users.all():
print "Yes, this user is in the Maths teachers organization!"
Но этот дизайн модели подразумевает, что когда я добавляю пользовательский объект в группу(напомню, что я хочу использовать функцию групповых разрешений django guardian ), я должен убедиться, что вызов save()
добавляет объект пользователя в группу «Учителя математики» вdjango.contrib.auth.models.Group
И в объект моего пользовательского класса TeachingTeam
«Учителя математики». И это не выглядит очень СУХИМ, не говоря уже о том, что я должен как-то гарантировать, что вызовы сохранения в обеих моделях выполняются в одном transaction
.
Существует ли лучший способ проектирования моих моделей с учетом этого варианта использования/требования -использовать группы django и в то же время обеспечить способ «расширения» функциональности собственных групп django (почти так же, как мы расширяем пользовательскую модель django с помощью «user профильное приложение" )?