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

"Could not build url for endpoint" when using nested blueprints #517

Open
ghost opened this issue Feb 12, 2023 · 3 comments · May be fixed by #543
Open

"Could not build url for endpoint" when using nested blueprints #517

ghost opened this issue Feb 12, 2023 · 3 comments · May be fixed by #543
Labels
bug Something isn't working

Comments

@ghost
Copy link

ghost commented Feb 12, 2023

Code

from myapi import api_v1

# Create the blueprints
api_blueprint = Blueprint("api", __name__, url_prefix="/api")
api_v1_blueprint = Blueprint("api_v1", __name__, url_prefix="/v1")

# Register the nested blueprint
api_blueprint.register_blueprint(api_v1_blueprint)

# Add the API to the nested blueprint
api_v1.init_app(api_v1_blueprint)

# Finally, register the parent blueprint to the app
app.register_blueprint(api_blueprint)

Repro Steps (if applicable)

  1. Go to the /api/v1 page

Expected Behavior

The interactive swagger documentation for api_v1 is shown

Actual Behavior

The exception Could not build url for endpoint 'api_v1.specs'. Did you mean 'api.api_v1.specs' instead? is raised

Error Messages/Stack Trace

127.0.0.1 - - [12/Feb/2023 20:20:32] "GET /api/v1/ HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 2548, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 2528, in wsgi_app
    response = self.handle_exception(e)
  File "/home/matthieu/.local/lib/python3.10/site-packages/flask_restx/api.py", line 674, in error_router
    return original_handler(e)
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/matthieu/.local/lib/python3.10/site-packages/flask_restx/api.py", line 674, in error_router
    return original_handler(e)
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
  File "/home/matthieu/.local/lib/python3.10/site-packages/flask_restx/api.py", line 456, in render_doc
    return apidoc.ui_for(self)
  File "/home/matthieu/.local/lib/python3.10/site-packages/flask_restx/apidoc.py", line 35, in ui_for
    return render_template("swagger-ui.html", title=api.title, specs_url=api.specs_url)
  File "/home/matthieu/.local/lib/python3.10/site-packages/flask_restx/api.py", line 542, in specs_url
    return url_for(
  File "/usr/lib/python3.10/site-packages/flask/helpers.py", line 256, in url_for
    return current_app.url_for(
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 2031, in url_for
    return self.handle_url_build_error(error, endpoint, values)
  File "/usr/lib/python3.10/site-packages/flask/app.py", line 2020, in url_for
    rv = url_adapter.build(  # type: ignore[union-attr]
  File "/usr/lib/python3.10/site-packages/werkzeug/routing/map.py", line 917, in build
    raise BuildError(endpoint, values, method, self)
werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'api_v1.specs'. Did you mean 'api.api_v1.specs' instead?

Environment

  • Python version: 3.10.9
  • Flask version: 2.2.2
  • Flask-RESTX version: 1.0.6
  • Other installed Flask extensions:
    • Flask-SQLAlchemy==2.5.1
    • flask-marshmallow==0.14.0
    • Flask-Login==0.6.2

Additional Context

This is the code used to define api_v1

api_v1 = Api(
    version="1.0",
    title="Test API",
    description="An API to test flask_restx",
    endpoint="/api/v1",
)
@ghost ghost added the bug Something isn't working label Feb 12, 2023
@peter-doggart
Copy link
Contributor

Flask-restx was written before Flask >2.0.0 introduced nested blueprints and therefore the Api class makes assumptions about the URLs and endpoints inside a Blueprint. I can't see any easy work around either.

Can I ask why you are interested in using nested blueprints rather than just registering another top level blueprint or using namespaces?

@ghost
Copy link
Author

ghost commented Feb 12, 2023

I'm interested in using nested blueprints since it seemed like the easiest way (mostly easy to register, as well as easy to add a redirect from /api to the latest API version).

As for namespaces, i am using them already to register various things to api_v1, but i don't really see how i could use it to have multiple different versions on the API with different prefix.

But if there isn't an easy way to fix it to work with nested blueprints, i'll follow your suggestion and use multiple top-level blueprints instead

@jakubman1 jakubman1 linked a pull request May 26, 2023 that will close this issue
jakubman1 added a commit to jakubman1/flask-restx that referenced this issue May 26, 2023
jakubman1 added a commit to jakubman1/flask-restx that referenced this issue May 26, 2023
jakubman1 added a commit to jakubman1/flask-restx that referenced this issue Jul 14, 2023
@Wankupi
Copy link

Wankupi commented Sep 27, 2024

I meet this problem today. It would be an useful change to support nested blueprint for me.

The problem I meet is:

  • the total website has a prefix. So there is a global blueprint web to set this prefix;
  • I want to bind api to a api blueprint first so that it won't depend on the outer blueprint web or the app. Thus I could decide the prefixes of all sub-blueprints together at web.register_blueprint.

Thanks for consideration!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants