98

許可ベースのシステムを使用して、Django アプリケーション内の特定のアクションを制限したいと考えています。これらのアクションは、特定のモデル (アプリケーション内のセクションへのアクセス、検索など) に関連付ける必要はありません。そのため、ストック パーミッション フレームワークを直接使用することはできません。これは、Permissionモデルがインストール済みのコンテンツ タイプへの参照を必要とするためです。

独自のパーミッション モデルを作成することもできますが、Django パーミッションに含まれる次のような機能をすべて書き直す必要があります。

django-authoritydjango-guardianなどのいくつかのアプリを確認しましたが、オブジェクトごとのアクセス許可を許可することで、モデル システムにさらに結合されたアクセス許可を提供しているようです。

Userプロジェクトのモデル (および以外) を定義せずに、このフレームワークを再利用する方法はありGroupますか?

4

8 に答える 8

61

Django のPermissionモデルにはインスタンスが必要ContentTypeです。

ContentTypeこれを回避する方法の 1 つは、どのモデルにも関係のないダミーを作成することだと思います(フィールドapp_labelmodelフィールドは任意の文字列値に設定できます)。

すべてをクリーンで適切なものにしたい場合は、ダミーの醜い詳細をすべて処理し、「モデルレス」パーミッション インスタンスを作成するPermission プロキシ モデルを作成できます。実際のモデルに関連するContentTypeすべてのインスタンスを除外するカスタム マネージャーを追加することもできます。Permission

于 2012-12-18T12:27:31.007 に答える
54

Gonzalo のアドバイスに従い、プロキシ モデルカスタム マネージャーを使用して、ダミーのコンテンツ タイプで「モデルレス」権限を処理しました。

from django.db import models
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType


class GlobalPermissionManager(models.Manager):
    def get_query_set(self):
        return super(GlobalPermissionManager, self).\
            get_query_set().filter(content_type__name='global_permission')


class GlobalPermission(Permission):
    """A global permission, not attached to a model"""

    objects = GlobalPermissionManager()

    class Meta:
        proxy = True

    def save(self, *args, **kwargs):
        ct, created = ContentType.objects.get_or_create(
            name="global_permission", app_label=self._meta.app_label
        )
        self.content_type = ct
        super(GlobalPermission, self).save(*args, **kwargs)
于 2012-12-19T12:09:05.840 に答える
10

いくつかのコメントで要求された、Django 1.8 での Chewie の回答を修正します。

リリースノートには次のように書かれています。

django.contrib.contenttypes.models.ContentType の name フィールドは移行によって削除され、プロパティに置き換えられました。つまり、このフィールドで ContentType をクエリまたはフィルター処理することはできなくなりました。

そのため、GlobalPermissions ではなく ContentType で参照されているのは「名前」です。

修正すると、次のようになります。

from django.db import models
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType


class GlobalPermissionManager(models.Manager):
    def get_queryset(self):
        return super(GlobalPermissionManager, self).\
            get_queryset().filter(content_type__model='global_permission')


class GlobalPermission(Permission):
    """A global permission, not attached to a model"""

    objects = GlobalPermissionManager()

    class Meta:
        proxy = True
        verbose_name = "global_permission"

    def save(self, *args, **kwargs):
        ct, created = ContentType.objects.get_or_create(
            model=self._meta.verbose_name, app_label=self._meta.app_label,
        )
        self.content_type = ct
        super(GlobalPermission, self).save(*args)

GlobalPermissionManager クラスは変更されていませんが、完全を期すために含まれています。

于 2015-06-24T15:50:36.737 に答える
2

proxy modelこれには、ダミーのコンテンツ タイプで を使用できます。

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType


class CustomPermission(Permission):

    class Meta:
        proxy = True

    def save(self, *args, **kwargs):
        ct, created = ContentType.objects.get_or_create(
            model=self._meta.verbose_name, app_label=self._meta.app_label,
        )
        self.content_type = ct
        super(CustomPermission, self).save(*args)

これで、モデルからのパーミッションのみnameでパーミッションを作成できます。codenameCustomPermission

 CustomPermission.objects.create(name='Can do something', codename='can_do_something')

また、次のように、テンプレート内のカスタム アクセス許可のみをクエリして表示できます。

 CustomPermission.objects.filter(content_type__model='custom permission')
于 2020-05-27T14:47:29.630 に答える
0

これを除いて、すべての答えは私にとって悪いです:

content_type = ContentType.objects.get_for_model(Permission)

Permission.objects.create(
    content_type=content_type,
    name='...', codename='...',
)

余分なものを追加せずにモデルのない権限を処理します。

于 2021-10-01T16:30:47.963 に答える