Django admin - 模型对超级用户可见,而不是员工用户

时间:2017-08-24 09:50:19

标签: mysql django django-admin migration

我知道syncdbmakemigrations,但我们只能在生产环境中这样做。

我们最近在生产中创建了几个表。正如预期的那样,任何用户都无法在管理员中看到表格 发布,我们在生产sql上手动执行了以下2个查询(我在我的本地运行迁移并执行了show create table查询以获取原始sql

django_content_type

INSERT INTO django_content_type(name, app_label, model) 
values ('linked_urls',"urls", 'linked_urls');

auth_permission

INSERT INTO auth_permission (name, content_type_id, codename) 
values 
('Can add linked_urls Table', (SELECT id FROM django_content_type where model='linked_urls' limit 1) ,'add_linked_urls'),
('Can change linked_urls Table', (SELECT id FROM django_content_type where model='linked_urls' limit 1) ,'change_linked_urls'),
('Can delete linked_urls Table', (SELECT id FROM django_content_type where model='linked_urls' limit 1) ,'delete_linked_urls');

现在这个模型在超级用户下可见,并且能够授予员工用户访问权限,但是员工用户无法看到它。
是否需要输入任何表条目?

或者,如果没有 syncdb 迁移,还有其他方法可以解决此问题吗?

2 个答案:

答案 0 :(得分:3)

  

我们最近在制作时创建了几张表。

我可以通过两种方式阅读你在那里写的内容。

第一种方式:您使用SQL语句创建了表,Django中没有相应的模型。如果是这种情况,那么任何会使Django突然使用这些表的内容类型和权限都无法摆弄。您需要为表创建模型。也许他们会unmanaged,但他们需要存在。

第二种方式:Django中的相应模型确实存在,您只需为它们手动创建表,这样就不会有问题。在这种情况下我要做的是运行以下代码,在代码之后进行解释:

from django.contrib.contenttypes.management import update_contenttypes
from django.apps import apps as configured_apps
from django.contrib.auth.management import create_permissions

for app in configured_apps.get_app_configs():
    update_contenttypes(app, interactive=True, verbosity=0)

for app in configured_apps.get_app_configs():
    create_permissions(app, verbosity=0)

上面的代码基本上是执行Django在运行迁移后执行的工作。当迁移发生时,Django只需根据需要创建表,然后在完成时调用update_contenttypes,它会扫描与项目中定义的模型关联的表,并将django_content_type表添加到表中待补充。然后,它调用create_permissions以使用需要添加的添加/更改/删除权限更新auth_permissions。我已经使用上面的代码强制提前创建权限during a migration。例如,如果我进行数据迁移,则会创建需要引用新权限的组。

答案 1 :(得分:1)

所以,最后我得到了一个解决方案。我在django上进行了大量的调试,并且在功能( at django.contrib.auth.backends )下面的apparanetly完成了提供权限的工作。

def _get_permissions(self, user_obj, obj, from_name):
    """
    Returns the permissions of `user_obj` from `from_name`. `from_name` can
    be either "group" or "user" to return permissions from
    `_get_group_permissions` or `_get_user_permissions` respectively.
    """
    if not user_obj.is_active or user_obj.is_anonymous() or obj is not None:
        return set()

    perm_cache_name = '_%s_perm_cache' % from_name
    if not hasattr(user_obj, perm_cache_name):
        if user_obj.is_superuser:
            perms = Permission.objects.all()
        else:
            perms = getattr(self, '_get_%s_permissions' % from_name)(user_obj)
        perms = perms.values_list('content_type__app_label', 'codename').order_by()
        setattr(user_obj, perm_cache_name, set("%s.%s" % (ct, name) for ct, name in perms))
    return getattr(user_obj, perm_cache_name)

那么问题是什么?

在此查询中出现问题:

INSERT INTO django_content_type(name, app_label, model) 
values ('linked_urls',"urls", 'linked_urls');

最初看起来不错,但执行的实际查询是:

--# notice the caps case here - it looked so trivial, i didn't even bothered to look into it untill i realised what was happening internally
INSERT INTO django_content_type(name, app_label, model) 
values ('Linked_Urls',"urls", 'Linked_Urls'); 

所以django在内部执行migrate时,确保所有内容都以小写 - 进行迁移,这就是问题 !!

我执行了单独的查询以小写所有先前的插入并 voila