Django admin - the model visible to the superuser, not to the user

I know syncdb and makemigrations , but we are limited to this in a production environment.

Recently, we had several tables created in production. As expected, the tables were not visible to the administrator for any user.
Publish that we had less than 2 manual queries in production sql (I migrated to my local server and made a show create table query to retrieve raw 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'); 

Now this model is visible under superuser and can also provide access to staff users, but user users do not see this.
Is there a record in the table that needs to be entered into it?

Or is there another way to solve this problem without syncdb migration?

+5
source share
2 answers

So finally, I had a solution. I debugged a lot on django and obviously below the function (with django.contrib.auth.backends ) it does the task of granting permissions.

 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) 

What is the problem?

The problem is with this query:

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

It looks fine, but the actual executed request:

 --# 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'); 

So, django, internally, when migrate executed, ensures that everything is lowercase - and that was the problem!

I had a separate request executed for the lower case of all previous inserts and voila!

+1
source

Recently, we had several tables created in production.

I can read what you wrote there in two ways.

The first way: you created tables with SQL statements for which there are no corresponding models in Django. If so, then there is no problem using content types and permissions that will force Django to suddenly use tables. You need to create models for tables. They may be unmanageable , but they must exist.

The second way: the corresponding models in Django exist, you just manually created tables for them, so this is not a problem. What would I do in this case, execute the following code, after the code there are explanations:

 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) 

What the above code does is essentially doing the work that Django does after starting the migration. When the migration occurs, Django simply creates the tables as needed, and then when it is done, it calls update_contenttypes , which scans the table associated with the models defined in the project and adds everything that needs to be added to the django_content_type table. He then calls create_permissions to update auth_permissions with the add / change / delete permissions that need to be added. I used the above code to force the creation of permissions early during the migration . This is useful if I have a data migration, for example, which creates groups that should reference the new permissions.

+3
source

Source: https://habr.com/ru/post/1271184/


All Articles