権限ベースのシステムを使用して、Djangoアプリケーション内の特定のアクションを制限します。これらのアクションは特定のモデルに関連する必要はありません(アプリケーションのセクションへのアクセス、検索など)。 。)、 ストックパーミッションフレームワーク を直接使用することはできません。これは、 Permission
モデルがインストールされたコンテンツタイプへの参照を必要とするためです。
独自のアクセス許可モデルを作成することもできますが、次に、Djangoアクセス許可に含まれるすべての特典を書き換える必要があります。
permission_required
デコレータ 。User.has_perm
および関連するユーザーメソッド。perms
テンプレート変数 。Django-authority や Django-guardian などのアプリをいくつかチェックしましたが、オブジェクトごとのアクセス許可を許可することで、モデルシステムにさらに結合したアクセス許可を提供するようです。
プロジェクトのモデル(User
およびGroup
以外)を定義せずにこのフレームワークを再利用する方法はありますか?
DjangoのPermission
モデル ContentType
インスタンスが必要 。
それを回避する1つの方法は、どのモデルにも関係しないダミーのContentType
を作成することだと思います(app_label
およびmodel
フィールドは、任意の文字列値に設定できます)。
すべてをきれいにしたい場合は、Permission
proxy model を作成して、ダミーのContentType
のい詳細をすべて処理し、「モデルレス」権限インスタンスを作成できます。 。また、実際のモデルに関連するすべてのPermission
インスタンスを除外するカスタムマネージャーを追加することもできます。
まだ検索しているあなたのために:
データベーステーブルなしで補助モデルを作成できます。そのモデルは、必要な許可をプロジェクトにもたらすことができます。 ContentTypeを処理したり、Permissionオブジェクトを明示的に作成したりする必要はありません。
from Django.db import models
class RightsSupport(models.Model):
class Meta:
managed = False # No database table creation or deletion \
# operations will be performed for this model.
permissions = (
('customer_rights', 'Global customer rights'),
('vendor_rights', 'Global vendor rights'),
('any_rights', 'Global any rights'),
)
直後の manage.py migrate
これらの権限は他の権限と同様に使用できます。
# Decorator
@permission_required('app.customer_rights')
def my_search_view(request):
…
# Inside a view
def my_search_view(request):
request.user.has_perm('app.customer_rights')
# In a template
# The currently logged-in user’s permissions are stored in the template variable {{ perms }}
{% if perms.app.customer_rigths %}
<p>You can do any customer stuff</p>
{% endif %}
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)
Django 1.8のChewieの答えを修正しました。これはいくつかのコメントで要求されました。
リリースノートには次のように書かれています:
Django.contrib.contenttypes.models.ContentTypeの名前フィールドは、移行によって削除され、プロパティに置き換えられました。つまり、このフィールドで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クラスは変更されていませんが、完全を期すために含まれています。
これは代替ソリューションです。最初に自問してください:DBには実際に存在するが、使用されることのないダミーモデルを作成して、許可を保持することを除きます。それはニースではありませんが、それは有効で簡単な解決策だと思います。
from Django.db import models
class Permissions(models.Model):
can_search_blue_flower = 'my_app.can_search_blue_flower'
class Meta:
permissions = [
('can_search_blue_flower', 'Allowed to search for the blue flower'),
]
上記のソリューションには、リテラル文字列「my_app.can_search_blue_flower」を使用する代わりに、ソースコードで変数Permissions.can_search_blue_flower
を使用できるという利点があります。これは、IDEのタイプミスを減らし、オートコンプリートを増やすことを意味します。
データベースにレコードを挿入するこのコードを記述して実行する代わりに、データベースにレコードを挿入するだけで済みます(明らかに必要に応じて主キーと外部キーを編集します)。
insert into Django_content_type(id,name,app_label,model) values (22,'app_permission','myapp','app_permission');
insert into auth_permission(id,name,content_type_id,codename) values (64,'Is Staff Member',22,'staff_member');
そして、アプリケーション管理者では、「スタッフメンバー」をユーザーまたはグループに割り当てることができます。クラスでこの許可を確認するには、次のように記述します。
from Django.contrib.auth.decorators import permission_required
from Django.utils.decorators import method_decorator
from Django.views.generic import TemplateView
class MyClass(TemplateView):
template_name = myapp/index.html'
@method_decorator(permission_required(['myapp.staff_member'],raise_exception=True))
def dispatch(self, *args, **kwargs):
return super(MyClass, self).dispatch(*args, **kwargs)