Django代理模型权限不会出现

时间:2013-02-23 06:03:36

标签: django django-models python-2.7 django-admin django-south

我为我的应用扩展了Django管理站点,允许非员工/超级用户访问。这工作正常。

我为现有模型创建了一个代理模型并将其注册到我的管理站点,但是,对于非员工用户,它不会出现。从我阅读的文档中,我的理解是代理模型获得了自己的权限。我检查过,这些没有出现在可用权限列表中。

这是我的代码,以防它有用:

普通模型

class Engagement(models.Model):
    eng_type = models.CharField(max_length=5)
    environment = models.CharField(max_length=8)    
    is_scoped = models.BooleanField()    

    class Meta:
        ordering = ['eng_type', 'environment']
        app_label = 'myapp'

代理模型

class NewRequests(Engagement):
    class Meta:
        proxy = True
        app_label = 'myapp'
        verbose_name = 'New Request'
        verbose_name_plural = 'New Requests'

模特管理员

class NewRequestsAdmin(ModelAdmin):
pass

def queryset(self, request):
    return self.model.objects.filter(is_scoped=0)

自定义管理员注册

myapps_admin_site.register(NewRequests, NewRequestsAdmin)

我一直在和南方管理我的数据库。根据{{​​3}},您必须按照this post进行一些篡改。这是一次失败。我的数据库中没有很多信息,因此我取消注释南并运行常规syncdb以排除South。不幸的是,这仍然没有用,我不知所措。任何帮助表示赞赏。

修改

这是关于Django 1.4

6 个答案:

答案 0 :(得分:7)

原来我没有做错任何事。我正在寻找

下的权限

myapp | New Request | Can add new request

权限属于父模型。

myapp | engagement | Can add new request

答案 1 :(得分:3)

有一种解决方法,您可以在此处查看:https://gist.github.com/magopian/7543724

它可能因您的django版本而异,但原则是相同的。

使用Django 1.10.1进行测试

/myproject/myapp/management/commands

如何使用

  • 创建目录/myproject/myapp/management/__init__.py
  • 创建文件/myproject/myapp/management/commands/__init__.py
  • 创建文件/myproject/myapp/management/commands/fix_permissions.py
  • 将上面的代码保存到/manage.py fix_permissions
  • 运行{{1}}

答案 2 :(得分:2)

这是Django中的已知错误:https://code.djangoproject.com/ticket/11154(检查某些补丁的评论)

答案 3 :(得分:1)

这在Django 2.2中已得到解决,引用了release notes

  

现在使用代理模型的内容类型而不是具体模型的内容类型创建代理模型的权限。迁移将在您运行迁移时更新现有权限。

docs

  

代理模型的工作方式与具体模型完全相同。使用代理模型自己的内容类型创建权限。代理模型不会继承其子类化的具体模型的权限。

答案 4 :(得分:0)

我意识到这个问题已经暂时关闭了,但是我会分享对我有用的东西,以防它可以帮助别人。

事实证明,即使我创建的代理模型的权限列在父应用程序下(如@chirinosky所示),即使我授予非超级用户所有权限,但仍然被拒绝通过管理员访问我的代理模型。

我必须做的是解决已知的Django错误(https://code.djangoproject.com/ticket/11154)并连接到post_syncdb信号以正确创建代理模型的权限。以下代码根据该主题的一些评论从https://djangosnippets.org/snippets/2677/修改。

我把它放在myapp / models.py中,它包含我的代理模型。从理论上讲,这可以存放在INSTALLED_APPS之后的任何django.contrib.contenttypes中,因为需要在update_contenttypes处理程序注册post_syncdb信号后加载,因此我们可以将其断开连接。< / p>

def create_proxy_permissions(app, created_models, verbosity, **kwargs):
    """
    Creates permissions for proxy models which are not created automatically
    by 'django.contrib.auth.management.create_permissions'.
    See https://code.djangoproject.com/ticket/11154
    Source: https://djangosnippets.org/snippets/2677/

    Since we can't rely on 'get_for_model' we must fallback to
    'get_by_natural_key'. However, this method doesn't automatically create
    missing 'ContentType' so we must ensure all the models' 'ContentType's are
    created before running this method. We do so by un-registering the
    'update_contenttypes' 'post_syncdb' signal and calling it in here just
    before doing everything.
    """
    update_contenttypes(app, created_models, verbosity, **kwargs)
    app_models = models.get_models(app)
    # The permissions we're looking for as (content_type, (codename, name))
    searched_perms = list()
    # The codenames and ctypes that should exist.
    ctypes = set()
    for model in app_models:
        opts = model._meta
        if opts.proxy:
            # Can't use 'get_for_model' here since it doesn't return
            # the correct 'ContentType' for proxy models.
            # See https://code.djangoproject.com/ticket/17648
            app_label, model = opts.app_label, opts.object_name.lower()
            ctype = ContentType.objects.get_by_natural_key(app_label, model)
            ctypes.add(ctype)
            for perm in _get_all_permissions(opts, ctype):
                searched_perms.append((ctype, perm))

    # Find all the Permissions that have a content_type for a model we're
    # looking for. We don't need to check for codenames since we already have
    # a list of the ones we're going to create.
    all_perms = set(Permission.objects.filter(
        content_type__in=ctypes,
    ).values_list(
        "content_type", "codename"
    ))

    objs = [
        Permission(codename=codename, name=name, content_type=ctype)
        for ctype, (codename, name) in searched_perms
        if (ctype.pk, codename) not in all_perms
    ]
    Permission.objects.bulk_create(objs)
    if verbosity >= 2:
        for obj in objs:
            sys.stdout.write("Adding permission '%s'" % obj)


models.signals.post_syncdb.connect(create_proxy_permissions)
# See 'create_proxy_permissions' docstring to understand why we un-register
# this signal handler.
models.signals.post_syncdb.disconnect(update_contenttypes)

答案 5 :(得分:0)

对于Django 1.11 由于 auth_permission 表中的 content_type_id 错误,此问题相关。 默认情况下,它会添加基本模型的内容类型,而不是代理模型内容类型。