从Django中删除(或隐藏)默认权限

时间:2011-05-19 17:42:14

标签: python django

我正在开发一个有两个管理后端的Django应用程序。一个用于“普通”用户的日常使用,默认用于更高级的任务和开发人员。

应用程序使用一些自定义权限,但不使用默认权限。所以我目前正在寻找一种方法来删除默认权限,或者至少有一种方法可以将它们从“每日”管理员后端隐藏起来,而无需进行大的修改。

8 个答案:

答案 0 :(得分:18)

更新:Django 1.7支持自定义default permissions

原始答案

以下内容适用于版本1.7之前的Django

这是auth contrib应用程序的标准功能。

它处理 post_syncdb 信号并创建权限(标准3:添加更改删除 ,每个型号,以及任何自定义的;它们存储在数据库的 auth_permission 表中。

因此,每次运行syncdb管理命令时都会创建

你有一些选择。没有什么是优雅的,但你可以考虑:

  1. 删除 auth contrib应用并提供您自己的authentication backend

    后果 - >您将失去在auth用户模型之上构建的管理员和其他自定义应用程序,但如果您的应用程序是高度自定义的,可以为您提供选项

  2. 覆盖auth app内部 post_syncdb 信号的行为(\django\contrib\auth\management__init__.py文件内)

    后果 - >请注意,如果没有基本权限,Django管理界面将无法工作(也可能是其他工作)。

  3. 删除 auth_permission 添加更改删除) > table(手动,脚本或其他)。

    后果 - >您将再次失去管理员,并且每次运行 syncdb 时都需要删除它们。

  4. 构建您自己的权限应用程序/系统(使用您自己的装饰器,中间件等)或扩展现有的。

    后果 - >没有,如果你把它建好 - 这是我认为最干净的解决方案之一。

  5. 最后的考虑:更改contrib应用程序或Django框架本身从来都不是一件好事:如果你需要升级到更新的版本,你可能会遇到困难Django的。

    所以,如果你想尽可能干净,可以考虑滚动自己的权限系统,或者扩展标准权限(django-guardian是django权限扩展的一个很好的例子)。它不会花费太多精力,您可以按照适合自己的方式构建它,克服标准django权限系统的限制。如果你做得很好,你也可以考虑开源,让其他人使用/改进你的解决方案=)

答案 1 :(得分:16)

我在这个问题上挣扎了一段时间,我想我已经找到了一个干净的解决方案。以下是隐藏Django的auth应用程序权限的方法:

from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from django import forms
from django.contrib.auth.models import Permission

class MyGroupAdminForm(forms.ModelForm):
    class Meta:
        model = MyGroup

    permissions = forms.ModelMultipleChoiceField(
        Permission.objects.exclude(content_type__app_label='auth'), 
        widget=admin.widgets.FilteredSelectMultiple(_('permissions'), False))


class MyGroupAdmin(admin.ModelAdmin):
    form = MyGroupAdminForm
    search_fields = ('name',)
    ordering = ('name',)

admin.site.unregister(Group)
admin.site.register(MyGroup, MyGroupAdmin)

当然可以轻松修改它以隐藏您想要的任何权限。如果这对您有用,请告诉我。

答案 2 :(得分:10)

Django 1.7中引入的新功能是定义默认权限的能力。如documentation中所述,如果将其设置为空,则不会创建任何默认权限。

一个工作的例子是:

class Blar1(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255, unique = True, blank = False, null = False, verbose_name= "Name")

    class Meta:
        default_permissions = ()

答案 3 :(得分:5)

ShadowCloud给出了一个很好的破坏。这是实现目标的简单方法。

在admin.py中添加以下内容:

from django.contrib.auth.models import Permission
admin.site.register(Permission)

您现在可以在管理员中添加/更改/删除权限。删除未使用的那些,当你有你想要的东西时,返回并从admin.py中删除这两行。

正如其他人所提到的,后续的syncdb会把所有东西都放回去。

答案 4 :(得分:2)

在@pmdarrow的解决方案的基础上,我提出了一个相对干净的解决方案来修补Django管理员视图。

请参阅:https://gist.github.com/vdboor/6280390

它扩展了UserGroup管理员以隐藏某些权限。

答案 5 :(得分:2)

您无法轻松删除这些权限(以便syncdb不会将其删回),但您可以将其隐藏在管理界面中。如其他人所述,这个想法是覆盖管理表单,但您必须为用户和组执行此操作。 这是带有解决方案的admin.py:

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Permission
from django.contrib.auth.models import User, Group
from django.contrib.auth.admin import GroupAdmin, UserAdmin
from django.contrib.auth.forms import UserChangeForm

#
# In the models listed below standard permissions "add_model", "change_model"
# and "delete_model" will be created by syncdb, but hidden from admin interface.
# This is convenient in case you use your own set of permissions so the list
# in the admin interface wont be confusing.
# Feel free to add your models here. The first element is the app name (this is
# the directory your app is in) and the second element is the name of your model
# from models.py module of your app (Note: both names must be lowercased).
#
MODELS_TO_HIDE_STD_PERMISSIONS = (
    ("myapp", "mymodel"),
)

def _get_corrected_permissions():
    perms = Permission.objects.all()
    for app_name, model_name in MODELS_TO_HIDE_STD_PERMISSIONS:
        perms = perms.exclude(content_type__app_label=app_name, codename='add_%s' % model_name)
        perms = perms.exclude(content_type__app_label=app_name, codename='change_%s' % model_name)
        perms = perms.exclude(content_type__app_label=app_name, codename='delete_%s' % model_name)
    return perms

class MyGroupAdminForm(forms.ModelForm):

    class Meta:
        model = Group

    permissions = forms.ModelMultipleChoiceField(
        _get_corrected_permissions(),
        widget=admin.widgets.FilteredSelectMultiple(('permissions'), False),
        help_text = 'Hold down "Control", or "Command" on a Mac, to select more than one.'
    )

class MyGroupAdmin(GroupAdmin):

    form = MyGroupAdminForm

class MyUserChangeForm(UserChangeForm):

    user_permissions = forms.ModelMultipleChoiceField(
        _get_corrected_permissions(),
        widget=admin.widgets.FilteredSelectMultiple(('user_permissions'), False),
        help_text = 'Hold down "Control", or "Command" on a Mac, to select more than one.'
    )

class MyUserAdmin(UserAdmin):

    form = MyUserChangeForm

admin.site.unregister(Group)
admin.site.register(Group, MyGroupAdmin)
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)

答案 6 :(得分:0)

如果您要创建自己的用户管理后端,并且只想显示自定义权限,则可以通过排除名称以“Can”开头的权限来过滤掉默认权限。

警告: 你必须记住不要以“Can”开头命名你的权限!!!! 如果他们决定更改命名约定,则可能无效。

归功于pmdarrow,这就是我在项目中的表现:

from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth.models import Permission
from django.contrib import admin    

class UserEditForm(UserChangeForm):
    class Meta:
        model = User

        exclude = (
                   'last_login',
                   'is_superuser',
                   'is_staff',
                   'date_joined',
                   )

    user_permissions = forms.ModelMultipleChoiceField(
        Permission.objects.exclude(name__startswith='Can'), 
        widget=admin.widgets.FilteredSelectMultiple(_('permissions'), False))

答案 7 :(得分:0)

如果您想阻止Django创建权限,您可以阻止发送信号。

如果你在任何应用程序中将它放入管理/ init .py,它将在auth框架有机会之前绑定到信号处理程序(利用dispatch_uid去抖动)。

from django.db.models import signals

def do_nothing(*args, **kwargs):
  pass

signals.post_syncdb.connect(do_nothing, dispatch_uid="django.contrib.auth.management.create_permissions")
signals.post_syncdb.connect(do_nothing, dispatch_uid="django.contrib.auth.management.create_superuser")