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.
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.
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.
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.