1

I am tring to add custom permissions to User model (django.contrib.auth.models).

To __init__.py file of my users app I add:

from django.db.models.signals import pre_migrate
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth import models as auth_models
from django.contrib.auth.models import Permission
from django.conf import settings
from django.dispatch import receiver


@receiver(pre_migrate, sender=auth_models)
def add_user_permissions(sender, **kwargs):
    content_type = ContentType.objects.get_for_model(settings.AUTH_USER_MODEL)
    Permission.objects.get_or_create(codename='view_user', name=' Can view users', content_type=content_type)
    Permission.objects.get_or_create(codename='change_user_password', name=' Can change user password', content_type=content_type)

settings.py:

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.forms',
    'django_select2',  # "django-select2" application
    'custom_app',  # "custom_app" application
    'custom_app_2',  # "custom_app_2" application
    'modeltranslation',  # "django-modeltranslation" application
    'users', # "users" application
]

ERROR:

Traceback (most recent call last):
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
    autoreload.raise_last_exception()
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/utils/autoreload.py", line 251, in raise_last_exception
    six.reraise(*_exception)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/utils/autoreload.py", line 228, in wrapper
    fn(*args, **kwargs)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/__init__.py", line 27, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/apps/registry.py", line 85, in populate
    app_config = AppConfig.create(entry)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/apps/config.py", line 94, in create
    module = import_module(entry)
  File "/usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/Applications/Projects/web/dashboard.kase.kz/users/__init__.py", line 5, in <module>
    from django.contrib.contenttypes.models import ContentType
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/contrib/contenttypes/models.py", line 139, in <module>
    class ContentType(models.Model):
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/db/models/base.py", line 110, in __new__
    app_config = apps.get_containing_app_config(module)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/apps/registry.py", line 247, in get_containing_app_config
    self.check_apps_ready()
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/apps/registry.py", line 125, in check_apps_ready
    raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

Question: How to fix this error?

Nurzhan Nogerbek
  • 4,806
  • 16
  • 87
  • 193
  • you need to add ```permission``` in INSTALLED_APPS. I think this will work for you. and also need add model level permission i.e in backend authentication. – Manoj Jadhav Nov 23 '17 at 04:37
  • @Nurzhan Nogerbek There might be a chance of duplicate entry for apps in your project like **users** I guess and also check the order as well. – Vijesh Venugopal Nov 23 '17 at 04:40
  • I have `'django.contrib.auth'` inside of `INSTALLED_APPS`. `permission` must be inside of the `django.contrib.auth`, right? – Nurzhan Nogerbek Nov 23 '17 at 04:40
  • @NurzhanNogerbek i think you should add ```django.contrib.auth``` and ```permission.backends.PermissionBackend``` in ```AUTHENTICATION_BACKENDS``` and also ```permission``` needs to be in installed app. – Manoj Jadhav Nov 23 '17 at 04:43
  • @ManojJadhav I add `'permission'` to `INSTALLED_APPS` and `AUTHENTICATION_BACKENDS=('permission.backends.PermissionBackend',)` to settings.py as you adviced but in terminal I see error like: `ImportError: No module named permission` – Nurzhan Nogerbek Nov 23 '17 at 05:25

3 Answers3

3

Finally I found solution from documentation.

1) You need to create empty migration with next command:

python manage.py makemigrations --empty users

users - name of the app

2) Command create 0001_initial.py file where you need to put next code:

# -*- coding: utf-8 -*-

from __future__ import unicode_literals
from django.db import migrations

def forwards_func(apps, schema_editor):
    User = apps.get_model('auth', 'User')
    Permission = apps.get_model('auth', 'Permission')
    ContentType = apps.get_model('contenttypes', 'ContentType')
    content_type = ContentType.objects.get_for_model(User)
    db_alias = schema_editor.connection.alias
    Permission.objects.using(db_alias).bulk_create([
        Permission(codename='view_user', name=' Can view users', content_type=content_type),
        Permission(codename='change_user_password', name=' Can change user password', content_type=content_type)
    ])


class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.RunPython(forwards_func),
    ]
Nurzhan Nogerbek
  • 4,806
  • 16
  • 87
  • 193
0

Please try adding this code at the top of the init.py file:

import django
django.setup()
Vijesh Venugopal
  • 1,621
  • 15
  • 26
  • Can you check my post again pls? I add full settings of `INSTALLED_APPS`. Is order correct? Also I add this code which you adviced but then I try to run server by `python manage.py runserver` command in terminal nothing happens. Do you have any ideas why this happens? – Nurzhan Nogerbek Nov 23 '17 at 04:52
  • Please refer this link for more details https://docs.djangoproject.com/en/1.11/ref/applications/#troubleshooting – Vijesh Venugopal Nov 23 '17 at 05:09
  • Thanks for this link ;) Docs say that this `exception is raised when attempting to use models before the app loading process, which initializes the ORM, is complete`. In `__init__.py` file I use only 2 models as you can see: `ContentType` and `Permission`. Error cause of them? – Nurzhan Nogerbek Nov 23 '17 at 05:23
  • Can you comment out them and check again? – Vijesh Venugopal Nov 23 '17 at 05:31
  • I am confused. What exactly I need to comment in `__init__.py` file? – Nurzhan Nogerbek Nov 23 '17 at 05:49
  • Comment the code sample where you import the models like **Permission** and **ContentType** – Vijesh Venugopal Nov 23 '17 at 05:51
  • I did as you said but the error is still the same =( Any other ideas? – Nurzhan Nogerbek Nov 23 '17 at 06:03
0

copy all code in your init.py to a new created file called signals.py and change your __init__.py to :

default_app_config = 'user.apps.UserConfig'

signals.py

from django.db.models.signals import pre_migrate
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import AuthConfig
from django.contrib.auth.models import Permission
from django.conf import settings
from django.dispatch import receiver


@receiver(pre_migrate, sender=AuthConfig)
def add_user_permissions(sender, **kwargs):
    content_type = ContentType.objects.get_for_model(settings.AUTH_USER_MODEL)
    Permission.objects.get_or_create(codename='view_user', name=' Can view users', content_type=content_type)
    Permission.objects.get_or_create(codename='change_user_password', name=' Can change user password', content_type=content_type)

then in user/apps.py:

from django.apps import AppConfig


class UserConfig(AppConfig):
    name = 'user'
    verbose_name = 'User'

    def ready(self):
        import user.signals

your error is occer because __init__.py will call User in models.py,but User model will be register after __init__.py run over,so you need call your signal when your User model is ready.


You want to add some perms related with User so:

class MyUser(User):

    class Meta:
        permissions = (
            ("view_user", "view_user"),
            ("change_user_password", "change_user_password"),
        )

and in settings.py

AUTH_USER_MODEL = "user.MyUser"
Ykh
  • 7,567
  • 1
  • 22
  • 31
  • I use your code. Now there are no errors but when I run `makemigrations`, `migrate` commands nothing happens. I mean custom permissions did not created =( Is code correct in `signals.py` file? – Nurzhan Nogerbek Nov 23 '17 at 08:41
  • In documentaion I found this: https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.models_module and it says that `the database related signals such as pre_migrate and post_migrate are only emitted for applications that have a models module`. `users` app has empty `models.py` file cause I use `User` model from box. Is it the reason of this behavior? – Nurzhan Nogerbek Nov 23 '17 at 09:39
  • I just now notice your additional amendment. I have some questions. I add `MyUser` to `models.py` file of `users` app. Is it mean that previous your code is not necessary now? Also I add your new code but it raise error. ERROR: `users.CustomUser.user_ptr: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out. HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.` – Nurzhan Nogerbek Nov 23 '17 at 11:28
  • When I changed in settings.py file to `AUTH_USER_MODEL = "users.models.MyUser"` it raise anouther error: `django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL must be of the form 'app_label.model_name'`. I am really confused now =( – Nurzhan Nogerbek Nov 23 '17 at 11:28
  • Also you last code create new model (new table) in DB after `migrate`, `makemigrations` commands? – Nurzhan Nogerbek Nov 23 '17 at 11:44
  • AUTH_USER_MODEL = "users.MyUser" – Ykh Nov 23 '17 at 15:25
  • `AUTH_USER_MODEL = "users.MyUser" ` raise error. Anyway I think its not good idea to create new model such as MyUser to create permissions to already existing User model. By the way I found solution. I use custom migration, check the answer. – Nurzhan Nogerbek Nov 24 '17 at 03:49