권한 기반 시스템을 사용하여 Django 애플리케이션 내에서 특정 작업을 제한하고 싶습니다. 이러한 작업은 특정 모델 (예 : 응용 프로그램의 섹션 액세스, 검색 …)과 관련 될 필요가 없습니다. 따라서 모델에 설치된 콘텐츠 유형에 대한 참조가 필요 하기 때문에 스톡 권한 프레임 워크를 직접 사용할 수 없습니다 Permission
.
나만의 권한 모델을 작성할 수 있지만 다음과 같이 Django 권한에 포함 된 모든 기능을 다시 작성해야합니다.
- 사용자 및 그룹에 권한을 할당 할 수 있습니다.
permission_required
장식 .User.has_perm
및 관련 사용자 방법.perms
템플릿 변수 .- …
django-authority 및 django-guardian 과 같은 일부 앱을 확인 했지만 객체 별 권한을 허용하여 모델 시스템과 더욱 결합 된 권한을 제공하는 것 같습니다.
프로젝트에 대한 모델 ( User
및 제외 Group
)을 정의하지 않고이 프레임 워크를 재사용 할 수있는 방법이 있습니까?
답변
Django의 Permission
모델 에는 ContentType
인스턴스 가 필요 합니다 .
한 가지 방법은 ContentType
모델과 관련이없는 더미 를 만드는 것입니다 ( app_label
및 model
필드는 모든 문자열 값으로 설정할 수 있음).
모든 것을 깔끔하고 멋지게 만들고 싶다면 더미의 모든 추악한 세부 사항을 처리하고 “모델없는”권한 인스턴스를 만드는 Permission
프록시 모델 을 만들 수 있습니다 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.
default_permissions = () # disable "add", "change", "delete"
# and "view" default permissions
permissions = (
('customer_rights', 'Global customer rights'),
('vendor_rights', 'Global vendor rights'),
('any_rights', 'Global any rights'),
)
마우스 오른쪽 후 manage.py makemigrations
와 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_rights %}
<p>You can do any customer stuff</p>
{% endif %}
답변
다음 곤잘로의 조언을 , 내가 사용하는 프록시 모델 과 사용자 정의 관리자를 더미 콘텐츠 형식으로 내 “modelless”권한을 처리 할 수 있습니다.
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'),
]
위의 솔루션은 Permissions.can_search_blue_flower
리터럴 문자열 “my_app.can_search_blue_flower”를 사용하는 대신 소스 코드에서 변수 를 사용할 수 있다는 이점이 있습니다 . 이것은 IDE에서 오타가 적고 자동 완성이 더 많다는 것을 의미합니다.
답변
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
과 권한 만 사용하여 권한을 만들 수 있습니다 .codename
CustomPermission
CustomPermission.objects.create(name='Can do something', codename='can_do_something')
그리고 이와 같이 템플릿에서 사용자 지정 권한 만 쿼리하고 표시 할 수 있습니다.
CustomPermission.objects.filter(content_type__model='custom permission')