Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuntimeError: Unable to resolve relationship user for wagtailcore.ModelLogEntry. Django is most likely not initialized, and its apps registry not populated. Ensure Django has finished setup before loading FilterSets #9586

Closed
Elrigor opened this issue Nov 3, 2022 · 12 comments
Labels
status:Unconfirmed Issue, usually a bug, that has not yet been validated as a confirmed problem. type:Bug
Milestone

Comments

@Elrigor
Copy link

Elrigor commented Nov 3, 2022

Hi!

I've updated to the LTS 4.1 but this error came out:

RuntimeError: Unable to resolve relationship `user` for `wagtailcore.ModelLogEntry`. Django is most likely not initialized, and its apps registry not populated. Ensure Django has finished setup before loading `FilterSet`s.

I have the following versions:

Wagtail 4.1
Django 4.0.8
django-filter 22.1]

My temporal "fix"

I was able to solve this by removing the user on the meta class of SnippetHistoryReportFilterSet :

    class Meta:
        model = ModelLogEntry
        fields = ["action", "**_user_**", "timestamp"]

This is located at wagtail/snippets/views/snippets.py

Is that a logger or something like that? If so, is there a way to disable it in order to use the page?

Thanks!

@Elrigor Elrigor added status:Unconfirmed Issue, usually a bug, that has not yet been validated as a confirmed problem. type:Bug labels Nov 3, 2022
@gasman gasman added this to the 4.1.1 milestone Nov 3, 2022
@gasman
Copy link
Collaborator

gasman commented Nov 3, 2022

Thanks for the report @Elrigor! We've had a couple of reports of similar issues (e.g. #9582), although we haven't yet definitively determined what triggers it. It looks quite likely that it's related to custom user models, though - are you using one on your project?

As another workaround, calling register_snippet from a wagtail_hooks.py rather than as a decorator on the model seems to help - as per the last code snippet under https://docs.wagtail.org/en/stable/topics/snippets.html#customising-snippets-admin-views (but leaving out the viewset argument, as that's optional).

@Elrigor
Copy link
Author

Elrigor commented Nov 3, 2022

Hi, Thank you for your fast reply!
I was able to fix it by using the default User model and not the custom one I have. However, I need to use a custom user model :/

@dkirkham
Copy link

dkirkham commented Nov 3, 2022

I'd have to roll back to an earlier commit in my project to confirm this, but I think I had a similar issue last week as I was coding the migration from 2.16 via 3.0 and 4.0 to 4.1rc1. It was resolved by putting the custom user module very early in the INSTALLED_APPS list (in settings), before any other module that referred to the user object.

@Elrigor
Copy link
Author

Elrigor commented Nov 3, 2022

That fixed it! Thank you mate 💯

@Elrigor Elrigor closed this as completed Nov 3, 2022
@gasman gasman reopened this Nov 3, 2022
@gasman
Copy link
Collaborator

gasman commented Nov 3, 2022

Reopening this, as we do want to find a proper fix for this that allows previously-working code to continue working on 4.1.

@laymonage
Copy link
Member

The filterset on the snippet history view has been there since 4.0, so I believe that's not the (only) cause.

In 4.1, we added this import, which causes the register_snippet function to load the wagtail.snippets.views.snippets module, which in turn imports the filterset before all models (including a custom User model) have been loaded in, raising this error.

@gasman
Copy link
Collaborator

gasman commented Nov 3, 2022

Reproduced on a fresh Wagtail project as follows:

wagtail start customusersnippet
cd customusersnippet
./manage.py startapp customuser

Add "customuser" to INSTALLED_APPS after "home", and edit customuser/models.py as follows:

from django.db import models

from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    country = models.CharField(verbose_name='country', max_length=255)

Add AUTH_USER_MODEL = 'customuser.CustomUser' to settings.

Edit home/models.py as follows:

from django.db import models

from wagtail.models import Page
from wagtail.snippets.models import register_snippet


class HomePage(Page):
    pass


@register_snippet
class Advert(models.Model):
    text = models.TextField()

Now ./manage.py makemigrations (or any other management command, e.g. ./manage.py check) fails with:

Traceback (most recent call last):
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django_filters/utils.py", line 174, in get_field_parts
    opts = field.remote_field.model._meta
AttributeError: 'str' object has no attribute '_meta'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django/core/management/__init__.py", line 420, in execute
    django.setup()
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django/apps/registry.py", line 116, in populate
    app_config.import_models()
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django/apps/config.py", line 269, in import_models
    self.models_module = import_module(models_module_name)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/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 "/Users/matthew/Development/tbx/wagtail/debug/customusersnippet/home/models.py", line 12, in <module>
    class Advert(models.Model):
  File "/Users/matthew/Development/tbx/wagtail/devscript/wagtail/wagtail/snippets/models.py", line 47, in register_snippet
    from wagtail.snippets.views.snippets import SnippetViewSet
  File "/Users/matthew/Development/tbx/wagtail/devscript/wagtail/wagtail/snippets/views/snippets.py", line 628, in <module>
    class SnippetHistoryReportFilterSet(WagtailFilterSet):
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django_filters/filterset.py", line 62, in __new__
    new_class.base_filters = new_class.get_filters()
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django_filters/filterset.py", line 325, in get_filters
    field = get_model_field(cls._meta.model, field_name)
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django_filters/utils.py", line 144, in get_model_field
    fields = get_field_parts(model, field_name)
  File "/Users/matthew/.virtualenvs/wagtail/lib/python3.8/site-packages/django_filters/utils.py", line 179, in get_field_parts
    raise RuntimeError(
RuntimeError: Unable to resolve relationship `user` for `wagtailcore.ModelLogEntry`. Django is most likely not initialized, and its apps registry not populated. Ensure Django has finished setup before loading `FilterSet`s.

Placing customuser first in INSTALLED_APPS avoids this.

@gasman
Copy link
Collaborator

gasman commented Nov 3, 2022

Bisecting shows that 6e1e024 is the commit that triggered this issue.

@ababic
Copy link
Contributor

ababic commented Nov 3, 2022

Suggestion: Would it be viable to update register_snippet() to simply store the Snippet: Custom ViewSet mappings in another global, then do the actual 'viewset registering' later on?

@gasman
Copy link
Collaborator

gasman commented Nov 3, 2022

@ababic That sounds like a good plan, yep! We're being a bit quirky with how we mix model and view code here, and while I think django-filter might be technically in the wrong for how early in the execution it's doing model lookups, making it less quirky wouldn't be a bad thing. :-)

@ababic
Copy link
Contributor

ababic commented Nov 4, 2022

@gasman I think you're right about django-filter. I think my suggestion needs something extra, otherwise users subclassing these viewsets and importing them into models.py to pass to register_snippet() are only going to bump into the same problem.

In addition to the above, maybe we make the 'viewset' argument accept a python path string? That way, we can keep that 'lazy' until we are ready to register views.

@gasman
Copy link
Collaborator

gasman commented Nov 4, 2022

@gasman I think you're right about django-filter. I think my suggestion needs something extra, otherwise users subclassing these viewsets and importing them into models.py to pass to register_snippet() are only going to bump into the same problem.

If people are building custom viewsets to pass to register_snippet, they'll probably be doing that in wagtail_hooks (as that's the documented and less messy approach), which means the issue doesn't arise (since wagtail_hooks is only imported later, after models have been loaded) - so I think we're covered.

gasman added a commit to gasman/wagtail that referenced this issue Nov 4, 2022
Fixes wagtail#9586. All calls to `register_snippet` that happen before `WagtailSnippetsAppConfig.ready` are now queued up and processed once we are sure models are fully loaded. This avoids any issues with unloaded models during viewset construction, as seen when subclassing django-filters's FilterSet.
@gasman gasman closed this as completed in 4d18e66 Nov 8, 2022
gasman added a commit that referenced this issue Nov 8, 2022
Fixes #9586. All calls to `register_snippet` that happen before `WagtailSnippetsAppConfig.ready` are now queued up and processed once we are sure models are fully loaded. This avoids any issues with unloaded models during viewset construction, as seen when subclassing django-filters's FilterSet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:Unconfirmed Issue, usually a bug, that has not yet been validated as a confirmed problem. type:Bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants