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

Router with basename is already registered #658

Closed
WafuRuns opened this issue Mar 20, 2024 · 9 comments · Fixed by #660
Closed

Router with basename is already registered #658

WafuRuns opened this issue Mar 20, 2024 · 9 comments · Fixed by #660

Comments

@WafuRuns
Copy link

It seems like some routes (specifically these in /tracker/api/urls.py)

router.register(
    r'events/(?P<event_pk>[^/.]+)/' + path + r'/feed_(?P<feed>\w+)',
    viewset,
    **kwargs,
)

and

router.register(r'events/(?P<event_pk>[^/.]+)/' + path, viewset, **kwargs)

have some problems as I'm constantly running into a django.core.exceptions.ImproperlyConfigured exception with comment: Router with basename "bid" is already registered. Please provide a unique basename for viewset "<class 'tracker.api.views.bids.BidViewSet'>"

Now this seems to go away if you just comment the lines and most parts of the tracker seem to work, but unfortunately, this is a consistently reproducible issue that I couldn't find a way around.

@uraniumanchor
Copy link
Collaborator

At what point are you getting this error? I can't reproduce this on any supported version of Django.

@WafuRuns
Copy link
Author

WafuRuns commented Mar 20, 2024

Running Python 3.10, I clone the donation-tracker, install it with the edit flag, then I install django 5.0 and create the basic project as in the readme. I do the installs in donation-tracker and set up the files just as in the guide, with analytics turned off. Then I run python manage.py migrate and python manage.py runserver - this is when I get the error. Nothing else, I'm following the guide almost 1:1 except for the migration and disabling analytics.

@WafuRuns
Copy link
Author

Just reconfirmed: Tried this with both Django 4.2 and 5.0, Python 3.10 and 3.12, all of them have the same problem and these two routes always break them, commenting them out builds the app, although I'm probably missing important things there. Full log below:

C:\Users\Wafu\Projects\gdqtracker2\tracker_development>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "C:\Users\Wafu\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1073, in _bootstrap_inner
    self.run()
  File "C:\Users\Wafu\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1010, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\core\management\commands\runserver.py", line 133, in inner_run
    self.check(display_num_errors=True)
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\core\management\base.py", line 485, in check
    all_issues = checks.run_checks(
                 ^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\core\checks\registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config
    return check_resolver(resolver)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver
    return check_method()
           ^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\urls\resolvers.py", line 494, in check
    for pattern in self.url_patterns:
                   ^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\urls\resolvers.py", line 715, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
                       ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\utils\functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\urls\resolvers.py", line 708, in urlconf_module
    return import_module(self.urlconf_name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\AppData\Local\Programs\Python\Python312\Lib\importlib\__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "C:\Users\Wafu\Projects\gdqtracker2\tracker_development\tracker_development\urls.py", line 4, in <module>
    import tracker.urls
  File "C:\Users\Wafu\Projects\gdqtracker2\donation-tracker\tracker\urls.py", line 56, in <module>
    path('api/v2/', include('tracker.api.urls', namespace='api_v2')),
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\django\urls\conf.py", line 38, in include
    urlconf_module = import_module(urlconf_module)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\AppData\Local\Programs\Python\Python312\Lib\importlib\__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Wafu\Projects\gdqtracker2\donation-tracker\tracker\api\urls.py", line 25, in <module>
    event_nested_route(r'bids', bids.BidViewSet, feed=True)
  File "C:\Users\Wafu\Projects\gdqtracker2\donation-tracker\tracker\api\urls.py", line 15, in event_nested_route
    router.register(
  File "C:\Users\Wafu\Projects\gdqtracker2\env\Lib\site-packages\rest_framework\routers.py", line 59, in register
    raise ImproperlyConfigured(msg)
django.core.exceptions.ImproperlyConfigured: Router with basename "bid" is already registered. Please provide a unique basename for viewset "<class 'tracker.api.views.bids.BidViewSet'>"

@uraniumanchor
Copy link
Collaborator

My guess is that something about your setup is causing that file to get imported twice. If you stick a print call right before that line do you see it in the logs more than once?

@WafuRuns
Copy link
Author

Yes, it logs twice. Not really sure where I could be doing anything wrong as I'm just following the instructions. But it also doesn't get through the register even for the first time, which is weird.

@WafuRuns
Copy link
Author

WafuRuns commented Mar 21, 2024

Update: I found out the reason why it logged twice. When manage.py is executed normally, it has an autoreloader function. Running it with python manage.py runserver --noreload seems to only execute everything once as intended.

However, it will still crash for those two routes I mentioned regardless of this. The issue must be somewhere in the routes setup itself.

Update: I can now 100% confirm that the issue happens within the event_nested_route. router.register(path, viewset) passes through, but any of the subsequent registers in that function won't. I believe it's because it somehow takes for example "bid" as the basename and then in this function adds 2 more routes with the same basename. If you comment any 2 routes in event_nested_route function, things pass through normally. So it's not really the regex routes that break, it's some data conflict after at least one of these routes is created.

@uraniumanchor
Copy link
Collaborator

uraniumanchor commented Mar 23, 2024

I was able to get this to occur, but only on Windows. Not sure yet why it would be different there. I'll take a look when I can.

Edit: It's something they changed in DRF. Looks like 3.15.0, because this autobump PR fails, and I hadn't had a chance to take a look at it yet:

#657

Relevant issue from DRF:

encode/django-rest-framework#8438

Workaround for now is to install DRF 3.14.0.

@WafuRuns
Copy link
Author

Had the same issue on Debian too. Looks like it works with DRF 3.14 though, thanks.

@uraniumanchor
Copy link
Collaborator

My other machines still had DRF 3.14 in their relevant environments so that's why it still worked there, since pip doesn't update existing packages unless you explicitly tell it to. My Windows machine was a completely fresh install, though, so it picked up 3.15 and broke.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants