我知道syncdb
和makemigrations
,但我们只能在生产环境中这样做。
我们最近在生产中创建了几个表。正如预期的那样,任何用户都无法在管理员中看到表格
发布,我们在生产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 ,迁移,还有其他方法可以解决此问题吗?
答案 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 !