Skip to content

Commit

Permalink
fix: correct blueprint name for nested blueprints
Browse files Browse the repository at this point in the history
Fixes issue python-restx#517.
  • Loading branch information
jakubman1 committed Jul 14, 2023
1 parent b1e5d19 commit cf87ea6
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
3 changes: 1 addition & 2 deletions doc/scaling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@ Use With Blueprints
-------------------

See :doc:`flask:blueprints` in the Flask documentation for what blueprints are and why you should use them.
Here's an example of how to link an :class:`Api` up to a :class:`~flask.Blueprint`. Nested Blueprints are
not supported.
Here's an example of how to link an :class:`Api` up to a :class:`~flask.Blueprint`.

.. code-block:: python
Expand Down
22 changes: 21 additions & 1 deletion flask_restx/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ def __init__(
self.resources = []
self.app = None
self.blueprint = None
self._blueprint_name = None
# must come after self.app initialisation to prevent __getattr__ recursion
# in self._configure_namespace_logger
self.default_namespace = self.namespace(
Expand Down Expand Up @@ -525,10 +526,29 @@ def namespace(self, *args, **kwargs):

def endpoint(self, name):
if self.blueprint:
return "{0}.{1}".format(self.blueprint.name, name)
if self._blueprint_name is None:
self._blueprint_name = self._get_blueprint_name()
return "{0}.{1}".format(self._blueprint_name, name)
else:
return name

def _get_blueprint_name(self):
"""
Get full blueprint name from the current_app.blueprints dict,
which contains full names for nested blueprints.
:rtype: str
"""
return next(
(
name
for name, bp in current_app.blueprints.items()
if bp == self.blueprint
),
# Fallback option when blueprint is not yet registered to the app.
self.blueprint.name,
)

@property
def specs_url(self):
"""
Expand Down
24 changes: 24 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,30 @@ def test_root_endpoint_with_blueprint_with_subdomain(self, app):
assert url == "http://api.localhost/api/"
assert api.base_url == "http://api.localhost/api/"

def test_root_endpoint_with_nested_blueprint(self, app):
blueprint = Blueprint("api", __name__, url_prefix="/api")
blueprint2 = Blueprint("v1", __name__, url_prefix="/v1")
blueprint.register_blueprint(blueprint2)
api = restx.Api(blueprint2, version="1.0")
app.register_blueprint(blueprint)

with app.test_request_context():
url = url_for("api.v1.root")
assert url == "/api/v1/"
assert api.base_url == "http://localhost/api/v1/"

def test_root_endpoint_with_nested_blueprint_with_subdomain(self, app):
blueprint = Blueprint("api", __name__, subdomain="api", url_prefix="/api")
blueprint2 = Blueprint("v1", __name__, url_prefix="/v1")
blueprint.register_blueprint(blueprint2)
api = restx.Api(blueprint2, version="1.0")
app.register_blueprint(blueprint)

with app.test_request_context():
url = url_for("api.v1.root")
assert url == "http://api.localhost/api/v1/"
assert api.base_url == "http://api.localhost/api/v1/"

def test_parser(self):
api = restx.Api()
assert isinstance(api.parser(), restx.reqparse.RequestParser)
Expand Down

0 comments on commit cf87ea6

Please sign in to comment.