django Guardian https://github.com/lukaszb/django-guardianは、オブジェクト レベルのパーミッション アプリとして非常によくできています。私は実際に、さまざまなdjangoプロジェクトで他のかなりの数のdjangoオブジェクトレベルのアクセス許可アプリを読んで使用しました。
私が取り組んでいる最近のプロジェクトでは、django ガーディアンを使用することにしましたが、2 つの可能なアプローチの長所と短所、および 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 ガーディアンが提供するグループ レベルのアクセス許可機能を利用するためです。
そのようなモデル設計は実用的ですか?
それとも、そのような別のモデル設計を使用したほうがよいのでしょうか...
アプローチ #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 ガーディアンのグループ アクセス許可機能を使用したいことを思い出してください)、save()
呼び出しによってユーザー オブジェクトが「Maths Teachers」グループに追加されることを確認する必要があるということです。 django.contrib.auth.models.Group
ANDをカスタムTeachingTeam
クラスの "Maths Teachers" オブジェクトに挿入します。そして、それはあまり DRY ではありません。言うまでもなく、両方のモデルへの保存呼び出しが単一のtransaction
.
このユースケース/要件を考慮してモデルを設計するより良い方法はありますか?djangoグループを使用し、djangoのネイティブグループ機能を「拡張」する方法を提供します(「ユーザープロファイルアプリ」でdjangoのユーザーモデルを拡張する方法とほぼ同じです) ?