Why does url_for() works with 'static' as first parameter? There's no static()

Question:

Can’t understand why it does work, so I can’t change it:

I’m using Flask-Admin’s ImageUploadField in a form, the field is this:

image = ImageUploadField(label='Optional image',
                         base_path=app.config['UPLOAD_FOLDER'],
                         relative_path=op.relpath(app.config['UPLOAD_FOLDER']),
                         endpoint='static'
                         )

endpoint='static' is the default value.

endpoint is used in flask_admin.ext.form.upload this way:

def get_url(self, field):
    if field.thumbnail_size:
        filename = field.thumbnail_fn(field.data)
    else:
        filename = field.data

    if field.url_relative_path:
        filename = urljoin(field.url_relative_path, filename)
    return url_for(field.endpoint, filename=filename)

So it’s being passed to an url_for() function…

the result of that url_for() is just prepending 'static/' to the filename. If I try to set

endpoint='some_string'

of course it raises a BuildError, but if I try to do:

#admin.py
class ProductForm(Form):
    order = IntegerField('order')
    name = TextField('name')
    category = SelectField('category', choices=[])
    image = ImageUploadField(label='Optional image',
                             base_path=app.config['UPLOAD_FOLDER'],
                             relative_path=op.relpath(app.config['UPLOAD_FOLDER']),
                             endpoint='dumb_f'
                             )
def dumb_f(str=''):
    return str

It raises the BuildError as well, I guess because dumb_f() is not visible in upload.py.

Why does url_for() even work? Shouldn’t the first parameter be the name of a function? I have no static named method, nor does upload.py have one.

Asked By: Luca Brozzi

||

Answers:

Flask provides the static endpoint for you.

Note that I used the word endpoint there; the url_for() function takes an endpoint name, and the @app.route() decorator defaults to using the function name as the endpoint name, but you are in no way required to use the function name.

Your code is not the only place routes and endpoints can be registered. The Flask app simply registered static when you created it, based on the default configuration.

See the Flask class definition source code:

# register the static folder for the application.  Do that even
# if the folder does not exist.  First of all it might be created
# while the server is running (usually happens during development)
# but also because google appengine stores static files somewhere
# else when mapped with the .yml file.
if self.has_static_folder:
    self.add_url_rule(self.static_url_path + '/<path:filename>',
                      endpoint='static',
                      view_func=self.send_static_file)

The app.add_url_rule() method registers a route too, and Flask specifies the endpoint argument explicitly here.

If you want to serve uploaded images from a different endpoint, you’ll have to register one yourself.

Answered By: Martijn Pieters
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.