-
-
Notifications
You must be signed in to change notification settings - Fork 16.2k
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
Nestable blueprints #593
Comments
I agree, this is something I'd like to see as well. I think the best use case would be a modular admin panel, where it is kept in a blueprint and plugins create sub-blueprints that are added to that blueprint. |
This comment has been minimized.
This comment has been minimized.
Not sure what the semantics are for this. If someone wants this, please come up with a design for it :) |
I think that dontcare4free's NestableBlueprint provides a good rough design. All that would really be needed is the ability to register blueprints onto an already existing blueprint. I don't think this would really change any code in Blueprint.register() either since, from looking at that and BlueprintSetupState, the same function names are shared between Blueprint and Flask. Looks like it'd be mostly a duplication of register_blueprint from Flask to Blueprint. Here is how I'd envision Blueprint.register_blueprint would work: Each blueprint would have its own self.blueprints dict. When register_blueprint is called, it would check whether there is a blueprint with that name already in its internal dict. The logic on what to depending on that result do is duplicated between Flask.register_blueprint and Blueprint.register_blueprint. However, the ID of the child blueprint would have the id of the parent blueprint appended to it, with a '.' between the two. For example, if the parent blueprint was named 'config' and the child blueprint was named 'users', then ultimately its ID would be 'config.users'. Any paths in the child would be prefixed by the parent blueprint's url_prefix as well as the child's. This is equally as rough as the dontcare4free's design above, and I haven't looked thoroughly through the code to see everywhere that this could affect, but it is possible to do. |
I'm also hoping for this. Right now, I'm implementing a RESTful API alongside a traditional web application and am ending up writing a lot of non-DRY code because I can't nest blueprints, particularly wrt API error handling (i.e., I have to override Flask's build-in error handling for each API blueprint in the same way). In fact, I'm thinking of trying out dontcare4free's NestableBlueprints subclass to see if it would help solve my problem. I'd love it if this were built in. |
I could use something like this as well. Not sure about the design, though – will test-drive it in my application. |
How strange - |
@Gioi I already suggested something along these lines once in IRC and got some arguments against it (by @mitsuhiko ? i don't remember) but i can't recall the points that were made against it. I also suck at grepping the logs. |
Personally, I like the idea of inheriting from a common class. I like to build my blueprints as fairly isolated from their siblings. It would be kind of nice if a blueprint was just a flask app itself. Perhaps there could be a distinction between blueprints that have to be bolted onto a parent, and blueprints/apps that can be run standalone. There is a lot of overlap between the two. I think bringing them closer together could really allow for some powerful uses. |
To elaborate on my personal use case: A specific application contains about two dozen blueprints. Most are coupled with a single entity (one pair for users, news posts, etc.) and contain the usual view methods (create, update, delete, etc.). However, some blueprints and entities belong together (news posts and images, gallery albums and images, etc.), and that's why I would like to group them together, but preferably without sacrificing the namespace-free view methods (as opposed to switching to So what I'm actually looking for is a way to group blueprints; but there is no need to (infinitely) nest them. |
@homeworkprod AFAIU, nestable blueprints would be a solution to your problem, right? |
@mitsuhiko Is this going anywhere? This seems like a great idea. |
@Gioi: Well, they would be a solution, but I'm worried that this would go too far. The initial post speaks of "sub-blueprints", and I think one additional layer would suffice (versus "nested", which, to me, sounds like multiple layers, and people could really go wild with that). But then again I might see a problem here that doesn't exist. |
Wouldn't a proper implementation of "sub-blueprints" pretty much automatically support infinite nesting of blueprints, too, anyway? |
Some questions to examine the current proposal:
@ThiefMaster: Well, I'd say it could get more complex, as it is usually the case with generalized implementations. But basically, yes, likely. |
The implementation in the OP doesn't handle this, but I think that makes the most sense. |
#750 a duplicate of this? |
@Turbo87 true, but @kennethreitz pretty much declined it with a back-to-the-drawing-board message. |
This would be extremely useful when designing applications, especially with a scenario like this (ala shopify):
Where the admin panel blueprint would be nest-able within the company page. |
I thought long and hard about this and whilst I absolutely agree that this would be very very nice to have it would require a rewrite of significant parts of flask (the way blueprints currently work under the hood is not very conducive of this) and I'm not sure it could be done in a completely backwards-compatible way. |
@danielchatfield: I don't see why it couldn't be backwards-compatible — as Currently, it seems that the best way to implement @employ's Shopify example with /admin consisting of multiple blueprints would be to make |
This issue has now been open for almost two years. In that time frame there has not been a single serious attempt at creating a properly designed solution, which would include documentation and considering the impact a discussion on the implications of this change and potential problems. Worse the discussion that has occured in this issue shows that fundamentally blueprints are probably a bad idea and better solutions for composing views might need to be found. So for all those who intend to add another +1 comment, take this under consideration and post something useful, if you want to see something happen or I'm just going to unsubscribe because quite frankly I don't care at all about how many +1s this gets apart from that it's filling my inbox. A sentiment I which I'm probably not alone with. |
A way to replace blueprints should probably start with finding out (or summarizing) what is actually wrong with blueprints. They don't seem like a very elegant solution to me, but i am not sure what problems should be solved by a replacement. I suggest deleting all 👍 comments for the sake of readability, and also to lock this issue and create a new one about a possible replacement or the future of blueprints. |
Why I need thisSay I wanna setup a admin page under /app
/admin
/monitor
__init__.py
monitor.py
/test
__init__.py
test.py
__init__.py
admin.py What I expect to do now is: from .test import test_bp
from .monitor import monitor_bp
admin_bp.register_blueprint(test_bp, url_preix='/test')
admin_bp.register_blueprint(monitor_bp, url_preix='/monitor') rather than: import test
import monitor
@admin_bp.add_url_rule('/test/test1', 'test1_view', test.test1_view)
@admin_bp.add_url_rule('/test/test2', 'test2_view', test.test2_view)
@admin_bp.add_url_rule('/monitor/page1', 'page1_view', monitor.page1_view)
@admin_bp.add_url_rule('/monitor/page2', 'page2_view', monitor.page2_view) Just something like |
A modification which returns the blueprint def add_blueprint(self, name, import_name, **kwargs):
url_subprefix = kwargs.pop('url_subprefix', None)
if url_subprefix:
kwargs.setdefault('url_prefix', self.url_prefix + url_subprefix)
bp = self.__class__(self.name + '.' + name, import_name, **kwargs)
def later(state):
state.app.register_blueprint(bp)
self.record(later)
return bp |
An alternative to sub-blueprints, is to break a one-file Blueprint into multiple py files, to import the secondary files in the main Blueprint file, and to then loop through the imported routes and call I created a Gist with the code for doing this: https://gist.github.com/Jaza/61f879f577bc9d06029e This doesn't provide sub-prefixing for the secondary routes, the way that nestable blueprints would (although in my use case I didn't want them anyway). Although, one could do auto-sub-prefixing in the |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Hi everyone, I appreciate that you're trying to help, but please stop posting variations of code that adds a prefix to all routes. The goal of nestable blueprints in Flask is to be fully nestable, including If this feature is important to you, please consider #3215 as a good place to start contributing. |
|
No, AFAICT this is just refactoring to reduce similar/duplicate code between Flask and Blueprint. |
I'd like to be able to register "sub-blueprints" using
Blueprint.register_blueprint(*args, **kwargs)
. This would register the nested blueprints with an app when the "parent" is registered with it. All parameters are preserved, other thanurl_prefix
, which is handled similarly to inadd_url_rule
. A naíve implementation could look like this:The text was updated successfully, but these errors were encountered: