django Guardian 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 组)时,组对象被创建并分配给这 3 个类中的一个,如果该组对象不属于它添加的类进入。
这意味着每个 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
是否是教学团队的一员,我需要做的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
AND到我的自定义TeachingTeam
课程的“数学教师”对象中。这感觉不是很干,更不用说我必须以某种方式确保对两个模型的保存调用都在一个transaction
.
鉴于此用例/要求,是否有更好的方法来设计我的模型 - 使用 django 组,但提供一种“扩展”django 的本机组功能的方法(几乎就像我们如何使用“用户配置文件应用程序”扩展 django 的用户模型一样) ?