Using url_for across blueprints

15,110

Solution 1

Short Answer: Yes

Long(ish) Answer:

As best I can tell, you're organizing your app the way you should.

I've recreated your setup (albeit in a single file), which you can checkout here. This code runs on my machine.

https://gist.github.com/enlore/80bf02346d6cabcba5b1

In flask, you can access a given view function with a relative endpoint (.login) from within the owning blueprint, or an via an absolute one (user.login) anywhere.

My money is on you having a typo in a view function name.

Like Mark Hildreth said in the comments, a great way to debug your problem would be to take a look at your url map.

>>> from app import app
>>> app.url_map
Map([<Rule '/login' (HEAD, OPTIONS, GET) -> user.login>,
 <Rule '/' (HEAD, OPTIONS, GET) -> pages.index>,
 <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
>>>

Solution 2

If you are using url_value_preprocessor make sure you are setting correctly the url_defaults otherwise url_for would not have enough values to build the url and you get this quite confusing error message.

Example.

@bp.url_value_preprocessor
def get_project(endpoint, values):
    project_name = values.pop('project_name')
    g.project = Project.query.filter_by(name=project_name).first_or_404()

@bp.url_defaults
def add_project(endpoint, values):
    if 'project_name' in values or not g.project:
        return
    values['project_name'] = g.project.name
Share:
15,110

Related videos on Youtube

arunjitsingh
Author by

arunjitsingh

Updated on September 14, 2022

Comments

  • arunjitsingh
    arunjitsingh over 1 year

    Does url_for work across blueprints?

    /flaskapp
        /runserver.py           (from server import app; app.run(debug=True))
        /server
            /__init__.py        (app = Flask(__name__))
            /pages
                /__init__.py    ('pages' blueprint)
            /users
                /__init__.py    ('users' blueprint)
    

    in server/__init__.py:

    from server.pages import pages
    from server.users import users
    
    app = Flask(__name__)
    
    app.register_blueprint(pages)
    app.register_blueprint(users)
    

    in server/pages/__init__.py:

    pages = Blueprint('pages', __name__)
    
    @pages.route('/')
    def index(): return '<h1>Index</h1>'
    

    in server/users/__init__.py:

    users = Blueprint('users', __name__)
    
    @users.route('/login')
    def login():
        ...
        return redirect(url_for('pages.index'))
                        ^^^^^^^^^^^^^^^^^^^^^^
    

    The url_for call raises BuildError: ('pages.index', {}, None) What would be a way to get to 'pages.index'?

    (I tried importing the module, but that didn't work)

    • Mark Hildreth
      Mark Hildreth over 10 years
      I've tried your example with Flask 0.10.1 and am unable to recreate the problem. This appears like it should work, perhaps you have left out of the question some code that is actually important? If possible, try to recreate the problem in a single python file and post that python file. Also, just before your app.debug, print to the console app.url_map, which will list all of the rules for the endpoints.