【发布时间】:2012-05-03 17:01:51
【问题描述】:
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 是否是 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 的组权限功能),我必须确保 @987654337 @call 将用户对象添加到django.contrib.auth.models.Group 中的“数学教师”组中AND 到我的自定义TeachingTeam 类的“数学教师”对象中。这感觉不是很干,更不用说我必须以某种方式确保对两个模型的保存调用都在单个 transaction 中完成。
鉴于此用例/要求,是否有更好的方法来设计我的模型 - 使用 django 组,但提供一种“扩展”django 的本机组功能的方法(几乎就像我们如何使用“用户配置文件”扩展 django 的用户模型一样)应用”)?
【问题讨论】:
-
在将对象与组链接时为什么不使用
OneToOne? -
因为与 User-to-Userprofile 关系(使用
OneToOne或ForeignKey,因为 1 个用户配置文件可能只与 1 个用户相关)不同,“组织”类可以与许多团体相关联。 -
那么 Django 组是什么意思呢?我认为您的组应该像用户配置文件一样继承 Django 的组(当然,我的意思是第一种方法)
-
django 组可能意味着特定类型组织中的不同组。例如,
StudentClass可以包含多个项目组。
标签: django django-models rbac