abhiabhi94 / django-flag-app

A pluggable django application that adds the ability for users to flag(or report) your models.
MIT License
14 stars 5 forks source link

Use of `get_user_model' at module level in manager causes circular import #19

Closed abhiabhi94 closed 3 years ago

abhiabhi94 commented 3 years ago
Exception in thread django-main-thread:
Traceback (most recent call last):
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\apps\config.py", line 178, in get_model
    return self.models[model_name.lower()]
KeyError: 'customuser'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\contrib\auth\__init__.py", line 157, in get_user_model
    return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\apps\registry.py", line 211, in get_model
    return app_config.get_model(model_name, require_ready=require_ready)
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\apps\config.py", line 180, in get_model
    raise LookupError(
LookupError: App 'users' doesn't have a 'CustomUser' model.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\tyler\appdata\local\programs\python\python38-32\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "c:\users\tyler\appdata\local\programs\python\python38-32\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\utils\autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\core\management\commands\runserver.py", line 110, in inner_run
    autoreload.raise_last_exception()
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\utils\autoreload.py", line 76, in raise_last_exception
    raise _exception[1]
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\core\management\__init__.py", line 357, in execute
    autoreload.check_errors(django.setup)()
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\utils\autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\apps\registry.py", line 114, in populate
    app_config.import_models()
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\apps\config.py", line 211, in import_models
    self.models_module = import_module(models_module_name)
  File "c:\users\tyler\appdata\local\programs\python\python38-32\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 783, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\Website\SHHASMRDBAPI\users\models.py", line 4, in <module>
    from api.models.artist_model import Artist
  File "C:\Website\SHHASMRDBAPI\api\models\__init__.py", line 2, in <module>
    from .video_model import Video
  File "C:\Website\SHHASMRDBAPI\api\models\video_model.py", line 7, in <module>
    from flag.models import Flag
  File "C:\Website\SHHASMRDBAPI\flag\models.py", line 11, in <module>
    from flag.managers import FlagInstanceManager, FlagManager
  File "C:\Website\SHHASMRDBAPI\flag\managers.py", line 6, in <module>
    from flag.utils import get_content_type, get_user_for_model
  File "C:\Website\SHHASMRDBAPI\flag\utils.py", line 12, in <module>
    User = get_user_model()
  File "C:\Users\Tyler\.virtualenvs\SHHASMRDBAPI-MStoyG3z\lib\site-packages\django\contrib\auth\__init__.py", line 161, in get_user_model
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'users.CustomUser' that has not been installed

_Originally posted by @TSolo315 in https://github.com/abhiabhi94/django-flag-app/pull/18#discussion_r589942499_

TSolo315 commented 3 years ago

My CustomUser model had a manytomany relationship with a Video model. The video model then had a flag field which would in turn call get_user_model() and lead to either circular import errors or the error listed above depending on the order of the Installed_apps list.

Solution: In CustomUser instead of importing the video model and initiating the field like:

favorite_videos = models.ManyToManyField(Video, blank=True, related_name='favorite_videos')

Don't import the video model and initialize like:

favorite_videos = models.ManyToManyField('api.Video', blank=True, related_name='favorite_videos')

abhiabhi94 commented 3 years ago

I have tried experimenting inside the testapp trying to reproduce your issue. You can check the branch fix/circular-import and tell me what needs to be done.

In short, it now has User model(which is equivalent to your CustomUser) inside the user_profile app. It acts as a foreign key to Post model of the post app. Now, the flag model is associated with this Post model. As of now, I can't reproduce the issue.

Just to be safe, have you added the location of your user model to settings.AUTH_USER_MODEL?

TSolo315 commented 3 years ago

Yes, I set settings.AUTH_USER_MODEL to my custom user model.

My user model included these relevant fields:

favorite_artists = models.ManyToManyField(Artist, blank=True, related_name='favorite_artists') blocked_artists = models.ManyToManyField(Artist, blank=True, related_name='blocked_artists') favorite_videos = models.ManyToManyField(Video, blank=True, related_name='favorite_videos') blocked_videos = models.ManyToManyField(Video, blank=True, related_name='blocked_videos')

The video model contains the flag field as well as a separate manytomany field pointing back to the user model via settings.AUTH_USER_MODEL and a foreign key relationship with the artist model.

I tested initializing with get_user_model() on a separate model and ran into the same issue so I don't think the problem is unique to this project.

abhiabhi94 commented 3 years ago

Can you just upload a minimum reproducible example in the form of a repository somewhere and share that link here? It will help me in seeing all the code, rather than shooting in the dark. As of now, I can't seem to reproduce the issue on my end.

TSolo315 commented 3 years ago

https://github.com/TSolo315/testflag

Ran into the issue making migrations for customUser after adding the many to many fields.

abhiabhi94 commented 3 years ago

Thanks, I will try to look into this when I have some more time today.

abhiabhi94 commented 3 years ago

Okay, so I could fix this by make these changes:

Please try to verify if it works at your end too.

Thanks for the report. If you can make these changes in #18, I will be happy to merge.

abhiabhi94 commented 3 years ago

Also, as a piece of advice, you may probably add a third field non-binary to your gender choices