【问题标题】:User permissions on proxy models in modeladminmodeladmin 中代理模型的用户权限
【发布时间】:2011-12-27 04:10:06
【问题描述】:

使用代理模型时:

class Uf(models.Model):
...

class CustomUf(Uf):
    class Meta:
        proxy = True

class CustomUfAdmin(admin.ModelAdmin)

admin.site.register(CustomUf, CustomUfAdmin)

似乎只有超级用户才能通过管理站点访问 CustomUf...我不知道如何将 CustomUf 的权限授予普通用户...

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    好的,克里斯关于内容类型的评论给了我提示......

    我在“admin.py”中定义代理对象时犯了一个错误。这样,您必须是超级管理员才能访问它。

    如果我在models.py中定义了代理对象,那么内容类型就会出现并且一切正常...

    【讨论】:

    • @Blaise 您是否使用 South 来管理应用程序?如果是,需要手动强制南触发post_syncdb,勾选here
    • 是的,这最终对我有用。必须到南方才能触发 post_synchdb。
    • 这在 Django 1.3 中对我有用。将代理模型移入models.py,重新运行syncdb。新权限!
    【解决方案2】:

    您需要再次运行 syncdb 以便获取新的内容类型。

    【讨论】:

    • 很抱歉,但它不起作用...当我为用户授予超级用户权限时,他可以访问 CustomUfAdmin 视图,但没有这些权限,它不起作用.. .
    • 如果您使用 South,这将不起作用,因为 syncdb 会跳过任何由 South 管理的应用程序。
    【解决方案3】:

    请参阅这个相关的 Django 问题:#11154

    您可以通过手动将行添加到“auth_permission”表来克服这个问题,例如:

    INSERT INTO "auth_permission" ("name","content_type_id","codename") 
        VALUES ('Can add proxy model name',{content_type_id},'add_proxy_model_name');
    

    其中内容类型 id 是相关内容类型的整数 id。

    【讨论】:

    • 接受的答案对我不起作用,但我可能把 appname/modelname 搞砸了。这行得通。
    • 我在这里编写了一个脚本来手动执行此操作。 stackoverflow.com/questions/5486018/…
    • 当代理模型位于基本模型之外的其他应用程序中时,这对我有帮助。即我在app_a 中定义了基本模型并在app_b 中定义了代理模型 - django 不会自动为我创建内容类型和权限。
    【解决方案4】:

    我意识到这个问题不久前就结束了,但我正在分享对我有用的方法,以防它可能对其他人有所帮助。

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

    如果您想避免 raw SQL 并在 Python 中编写修复脚本,您必须解决已知的 Django 错误 (https://code.djangoproject.com/ticket/11154) 并连接到 post_syncdb 信号以正确创建代理模型的权限。下面的代码是根据该线程上的一些 cmets 从 https://djangosnippets.org/snippets/2677/ 修改而来的。

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

    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)
    

    【讨论】:

      猜你喜欢
      • 2014-02-22
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 2018-04-10
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多