forked from orbit-oss/flask
Refactored static folder registration
This commit is contained in:
parent
fedc06c295
commit
15012af700
3 changed files with 60 additions and 19 deletions
27
flask/app.py
27
flask/app.py
|
|
@ -10,7 +10,6 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import posixpath
|
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
@ -21,7 +20,7 @@ from werkzeug.routing import Map, Rule
|
||||||
from werkzeug.exceptions import HTTPException, InternalServerError, NotFound
|
from werkzeug.exceptions import HTTPException, InternalServerError, NotFound
|
||||||
|
|
||||||
from flask.helpers import _PackageBoundObject, url_for, get_flashed_messages, \
|
from flask.helpers import _PackageBoundObject, url_for, get_flashed_messages, \
|
||||||
_tojson_filter, send_file
|
_tojson_filter
|
||||||
from flask.wrappers import Request, Response
|
from flask.wrappers import Request, Response
|
||||||
from flask.config import ConfigAttribute, Config
|
from flask.config import ConfigAttribute, Config
|
||||||
from flask.ctx import _default_template_ctx_processor, _RequestContext
|
from flask.ctx import _default_template_ctx_processor, _RequestContext
|
||||||
|
|
@ -101,6 +100,9 @@ class Flask(_PackageBoundObject):
|
||||||
#: Path for the static files. If you don't want to use static files
|
#: Path for the static files. If you don't want to use static files
|
||||||
#: you can set this value to `None` in which case no URL rule is added
|
#: you can set this value to `None` in which case no URL rule is added
|
||||||
#: and the development server will no longer serve any static files.
|
#: and the development server will no longer serve any static files.
|
||||||
|
#:
|
||||||
|
#: This is the default used for application and modules unless a
|
||||||
|
#: different value is passed to the constructor.
|
||||||
static_path = '/static'
|
static_path = '/static'
|
||||||
|
|
||||||
#: The debug flag. Set this to `True` to enable debugging of the
|
#: The debug flag. Set this to `True` to enable debugging of the
|
||||||
|
|
@ -190,8 +192,10 @@ class Flask(_PackageBoundObject):
|
||||||
'SERVER_NAME': None
|
'SERVER_NAME': None
|
||||||
})
|
})
|
||||||
|
|
||||||
def __init__(self, import_name):
|
def __init__(self, import_name, static_path=None):
|
||||||
_PackageBoundObject.__init__(self, import_name)
|
_PackageBoundObject.__init__(self, import_name)
|
||||||
|
if static_path is not None:
|
||||||
|
self.static_path = static_path
|
||||||
|
|
||||||
#: The configuration dictionary as :class:`Config`. This behaves
|
#: The configuration dictionary as :class:`Config`. This behaves
|
||||||
#: exactly like a regular dictionary but supports additional methods
|
#: exactly like a regular dictionary but supports additional methods
|
||||||
|
|
@ -258,7 +262,8 @@ class Flask(_PackageBoundObject):
|
||||||
#: app.url_map.converters['list'] = ListConverter
|
#: app.url_map.converters['list'] = ListConverter
|
||||||
self.url_map = Map()
|
self.url_map = Map()
|
||||||
|
|
||||||
if self.static_path is not None:
|
# if there is a static folder, register it for the application.
|
||||||
|
if self.has_static_folder:
|
||||||
self.add_url_rule(self.static_path + '/<filename>',
|
self.add_url_rule(self.static_path + '/<filename>',
|
||||||
endpoint='static',
|
endpoint='static',
|
||||||
view_func=self.send_static_file)
|
view_func=self.send_static_file)
|
||||||
|
|
@ -377,20 +382,6 @@ class Flask(_PackageBoundObject):
|
||||||
options.setdefault('use_debugger', self.debug)
|
options.setdefault('use_debugger', self.debug)
|
||||||
return run_simple(host, port, self, **options)
|
return run_simple(host, port, self, **options)
|
||||||
|
|
||||||
def send_static_file(self, filename):
|
|
||||||
"""Function used internally to send static files from the static
|
|
||||||
folder to the browser.
|
|
||||||
|
|
||||||
.. versionadded:: 0.5
|
|
||||||
"""
|
|
||||||
filename = posixpath.normpath(filename)
|
|
||||||
if filename.startswith('../'):
|
|
||||||
raise NotFound()
|
|
||||||
filename = os.path.join(self.root_path, 'static', filename)
|
|
||||||
if not os.path.isfile(filename):
|
|
||||||
raise NotFound()
|
|
||||||
return send_file(filename, conditional=True)
|
|
||||||
|
|
||||||
def test_client(self):
|
def test_client(self):
|
||||||
"""Creates a test client for this application. For information
|
"""Creates a test client for this application. For information
|
||||||
about unit testing head over to :ref:`testing`.
|
about unit testing head over to :ref:`testing`.
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import posixpath
|
||||||
import mimetypes
|
import mimetypes
|
||||||
from time import time
|
from time import time
|
||||||
from zlib import adler32
|
from zlib import adler32
|
||||||
|
|
@ -330,6 +331,29 @@ class _PackageBoundObject(object):
|
||||||
#: Where is the app root located?
|
#: Where is the app root located?
|
||||||
self.root_path = _get_package_path(self.import_name)
|
self.root_path = _get_package_path(self.import_name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_static_folder(self):
|
||||||
|
"""This is `True` if the package bound object's container has a
|
||||||
|
folder named ``'static'``.
|
||||||
|
|
||||||
|
.. versionadded:: 0.5
|
||||||
|
"""
|
||||||
|
return os.path.isdir(os.path.join(self.root_path, 'static'))
|
||||||
|
|
||||||
|
def send_static_file(self, filename):
|
||||||
|
"""Function used internally to send static files from the static
|
||||||
|
folder to the browser.
|
||||||
|
|
||||||
|
.. versionadded:: 0.5
|
||||||
|
"""
|
||||||
|
filename = posixpath.normpath(filename)
|
||||||
|
if filename.startswith('../'):
|
||||||
|
raise NotFound()
|
||||||
|
filename = os.path.join(self.root_path, 'static', filename)
|
||||||
|
if not os.path.isfile(filename):
|
||||||
|
raise NotFound()
|
||||||
|
return send_file(filename, conditional=True)
|
||||||
|
|
||||||
def open_resource(self, resource):
|
def open_resource(self, resource):
|
||||||
"""Opens a resource from the application's resource folder. To see
|
"""Opens a resource from the application's resource folder. To see
|
||||||
how this works, consider the following folder structure::
|
how this works, consider the following folder structure::
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,27 @@
|
||||||
from flask.helpers import _PackageBoundObject
|
from flask.helpers import _PackageBoundObject
|
||||||
|
|
||||||
|
|
||||||
|
def _register_module_static(module):
|
||||||
|
"""Internal helper function that returns a function for recording
|
||||||
|
that registers the `send_static_file` function for the module on
|
||||||
|
the application of necessary.
|
||||||
|
"""
|
||||||
|
def _register_static(state):
|
||||||
|
# do not register the rule if the static folder of the
|
||||||
|
# module is the same as the one from the application.
|
||||||
|
if state.app.root_path == module.root_path:
|
||||||
|
return
|
||||||
|
path = static_path
|
||||||
|
if path is None:
|
||||||
|
path = state.app.static_path
|
||||||
|
if state.url_prefix:
|
||||||
|
path = state.url_prefix + path
|
||||||
|
state.app.add_url_rule(path + '/<filename>',
|
||||||
|
'%s.static' % module.name,
|
||||||
|
view_func=module.send_static_file)
|
||||||
|
return _register_static
|
||||||
|
|
||||||
|
|
||||||
class _ModuleSetupState(object):
|
class _ModuleSetupState(object):
|
||||||
|
|
||||||
def __init__(self, app, url_prefix=None):
|
def __init__(self, app, url_prefix=None):
|
||||||
|
|
@ -67,7 +88,8 @@ class Module(_PackageBoundObject):
|
||||||
:ref:`working-with-modules` section.
|
:ref:`working-with-modules` section.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, import_name, name=None, url_prefix=None):
|
def __init__(self, import_name, name=None, url_prefix=None,
|
||||||
|
static_path=None):
|
||||||
if name is None:
|
if name is None:
|
||||||
assert '.' in import_name, 'name required if package name ' \
|
assert '.' in import_name, 'name required if package name ' \
|
||||||
'does not point to a submodule'
|
'does not point to a submodule'
|
||||||
|
|
@ -77,6 +99,10 @@ class Module(_PackageBoundObject):
|
||||||
self.url_prefix = url_prefix
|
self.url_prefix = url_prefix
|
||||||
self._register_events = []
|
self._register_events = []
|
||||||
|
|
||||||
|
# if there is a static folder, register it for this module
|
||||||
|
if self.has_static_folder:
|
||||||
|
self._record(_register_module_static(self))
|
||||||
|
|
||||||
def route(self, rule, **options):
|
def route(self, rule, **options):
|
||||||
"""Like :meth:`Flask.route` but for a module. The endpoint for the
|
"""Like :meth:`Flask.route` but for a module. The endpoint for the
|
||||||
:func:`url_for` function is prefixed with the name of the module.
|
:func:`url_for` function is prefixed with the name of the module.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue