Skip to content

Commit a041906

Browse files
committed
fix: correct blueprint name for nested blueprints
Fixes issue #517.
1 parent ad2210c commit a041906

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

flask_restx/api.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ def __init__(
183183
self.resources = []
184184
self.app = None
185185
self.blueprint = None
186+
self._blueprint_name = None
186187
# must come after self.app initialisation to prevent __getattr__ recursion
187188
# in self._configure_namespace_logger
188189
self.default_namespace = self.namespace(
@@ -525,10 +526,29 @@ def namespace(self, *args, **kwargs):
525526

526527
def endpoint(self, name):
527528
if self.blueprint:
528-
return "{0}.{1}".format(self.blueprint.name, name)
529+
if self._blueprint_name is None:
530+
self._blueprint_name = self._get_blueprint_name()
531+
return "{0}.{1}".format(self._blueprint_name, name)
529532
else:
530533
return name
531534

535+
def _get_blueprint_name(self):
536+
"""
537+
Get full blueprint name from the current_app.blueprints dict,
538+
which contains full names for nested blueprints.
539+
540+
:rtype: str
541+
"""
542+
return next(
543+
(
544+
name
545+
for name, bp in current_app.blueprints.items()
546+
if bp == self.blueprint
547+
),
548+
# Fallback option when blueprint is not yet registered to the app.
549+
self.blueprint.name,
550+
)
551+
532552
@property
533553
def specs_url(self):
534554
"""

tests/test_api.py

+24
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,30 @@ def test_root_endpoint_with_blueprint_with_subdomain(self, app):
4343
assert url == "http://api.localhost/api/"
4444
assert api.base_url == "http://api.localhost/api/"
4545

46+
def test_root_endpoint_with_nested_blueprint(self, app):
47+
blueprint = Blueprint("api", __name__, url_prefix="/api")
48+
blueprint2 = Blueprint("v1", __name__, url_prefix="/v1")
49+
blueprint.register_blueprint(blueprint2)
50+
api = restx.Api(blueprint2, version="1.0")
51+
app.register_blueprint(blueprint)
52+
53+
with app.test_request_context():
54+
url = url_for("api.v1.root")
55+
assert url == "/api/v1/"
56+
assert api.base_url == "http://localhost/api/v1/"
57+
58+
def test_root_endpoint_with_nested_blueprint_with_subdomain(self, app):
59+
blueprint = Blueprint("api", __name__, subdomain="api", url_prefix="/api")
60+
blueprint2 = Blueprint("v1", __name__, url_prefix="/v1")
61+
blueprint.register_blueprint(blueprint2)
62+
api = restx.Api(blueprint2, version="1.0")
63+
app.register_blueprint(blueprint)
64+
65+
with app.test_request_context():
66+
url = url_for("api.v1.root")
67+
assert url == "http://api.localhost/api/v1/"
68+
assert api.base_url == "http://api.localhost/api/v1/"
69+
4670
def test_parser(self):
4771
api = restx.Api()
4872
assert isinstance(api.parser(), restx.reqparse.RequestParser)

0 commit comments

Comments
 (0)