änderung1
This commit is contained in:
1 parent
cc1d096bc3
commit
cbdda613b7
2098 files changed
+274524
No files matched your search
@@ -0,0 +1,14 @@
|
||||
from django.contrib.staticfiles.finders import get_finders
|
||||
|
||||
|
||||
def check_finders(app_configs=None, **kwargs):
|
||||
"""Check all registered staticfiles finders."""
|
||||
errors = []
|
||||
for finder in get_finders():
|
||||
try:
|
||||
finder_errors = finder.check()
|
||||
except NotImplementedError:
|
||||
pass
|
||||
else:
|
||||
errors.extend(finder_errors)
|
||||
return errors
|
||||
@@ -0,0 +1,296 @@
|
||||
import functools
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles import utils
|
||||
from django.core.checks import Error
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.files.storage import (
|
||||
FileSystemStorage, Storage, default_storage,
|
||||
)
|
||||
from django.utils._os import safe_join
|
||||
from django.utils.functional import LazyObject, empty
|
||||
from django.utils.module_loading import import_string
|
||||
|
||||
# To keep track on which directories the finder has searched the static files.
|
||||
searched_locations = []
|
||||
|
||||
|
||||
class BaseFinder:
|
||||
"""
|
||||
A base file finder to be used for custom staticfiles finder classes.
|
||||
"""
|
||||
def check(self, **kwargs):
|
||||
raise NotImplementedError(
|
||||
'subclasses may provide a check() method to verify the finder is '
|
||||
'configured correctly.'
|
||||
)
|
||||
|
||||
def find(self, path, all=False):
|
||||
"""
|
||||
Given a relative file path, find an absolute file path.
|
||||
|
||||
If the ``all`` parameter is False (default) return only the first found
|
||||
file path; if True, return a list of all found files paths.
|
||||
"""
|
||||
raise NotImplementedError('subclasses of BaseFinder must provide a find() method')
|
||||
|
||||
def list(self, ignore_patterns):
|
||||
"""
|
||||
Given an optional list of paths to ignore, return a two item iterable
|
||||
consisting of the relative path and storage instance.
|
||||
"""
|
||||
raise NotImplementedError('subclasses of BaseFinder must provide a list() method')
|
||||
|
||||
|
||||
class FileSystemFinder(BaseFinder):
|
||||
"""
|
||||
A static files finder that uses the ``STATICFILES_DIRS`` setting
|
||||
to locate files.
|
||||
"""
|
||||
def __init__(self, app_names=None, *args, **kwargs):
|
||||
# List of locations with static files
|
||||
self.locations = []
|
||||
# Maps dir paths to an appropriate storage instance
|
||||
self.storages = OrderedDict()
|
||||
for root in settings.STATICFILES_DIRS:
|
||||
if isinstance(root, (list, tuple)):
|
||||
prefix, root = root
|
||||
else:
|
||||
prefix = ''
|
||||
if (prefix, root) not in self.locations:
|
||||
self.locations.append((prefix, root))
|
||||
for prefix, root in self.locations:
|
||||
filesystem_storage = FileSystemStorage(location=root)
|
||||
filesystem_storage.prefix = prefix
|
||||
self.storages[root] = filesystem_storage
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def check(self, **kwargs):
|
||||
errors = []
|
||||
if not isinstance(settings.STATICFILES_DIRS, (list, tuple)):
|
||||
errors.append(Error(
|
||||
'The STATICFILES_DIRS setting is not a tuple or list.',
|
||||
hint='Perhaps you forgot a trailing comma?',
|
||||
id='staticfiles.E001',
|
||||
))
|
||||
for root in settings.STATICFILES_DIRS:
|
||||
if isinstance(root, (list, tuple)):
|
||||
prefix, root = root
|
||||
if prefix.endswith('/'):
|
||||
errors.append(Error(
|
||||
'The prefix %r in the STATICFILES_DIRS setting must '
|
||||
'not end with a slash.' % prefix,
|
||||
id='staticfiles.E003',
|
||||
))
|
||||
if settings.STATIC_ROOT and os.path.abspath(settings.STATIC_ROOT) == os.path.abspath(root):
|
||||
errors.append(Error(
|
||||
'The STATICFILES_DIRS setting should not contain the '
|
||||
'STATIC_ROOT setting.',
|
||||
id='staticfiles.E002',
|
||||
))
|
||||
return errors
|
||||
|
||||
def find(self, path, all=False):
|
||||
"""
|
||||
Look for files in the extra locations as defined in STATICFILES_DIRS.
|
||||
"""
|
||||
matches = []
|
||||
for prefix, root in self.locations:
|
||||
if root not in searched_locations:
|
||||
searched_locations.append(root)
|
||||
matched_path = self.find_location(root, path, prefix)
|
||||
if matched_path:
|
||||
if not all:
|
||||
return matched_path
|
||||
matches.append(matched_path)
|
||||
return matches
|
||||
|
||||
def find_location(self, root, path, prefix=None):
|
||||
"""
|
||||
Find a requested static file in a location and return the found
|
||||
absolute path (or ``None`` if no match).
|
||||
"""
|
||||
if prefix:
|
||||
prefix = '%s%s' % (prefix, os.sep)
|
||||
if not path.startswith(prefix):
|
||||
return None
|
||||
path = path[len(prefix):]
|
||||
path = safe_join(root, path)
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
|
||||
def list(self, ignore_patterns):
|
||||
"""
|
||||
List all files in all locations.
|
||||
"""
|
||||
for prefix, root in self.locations:
|
||||
storage = self.storages[root]
|
||||
for path in utils.get_files(storage, ignore_patterns):
|
||||
yield path, storage
|
||||
|
||||
|
||||
class AppDirectoriesFinder(BaseFinder):
|
||||
"""
|
||||
A static files finder that looks in the directory of each app as
|
||||
specified in the source_dir attribute.
|
||||
"""
|
||||
storage_class = FileSystemStorage
|
||||
source_dir = 'static'
|
||||
|
||||
def __init__(self, app_names=None, *args, **kwargs):
|
||||
# The list of apps that are handled
|
||||
self.apps = []
|
||||
# Mapping of app names to storage instances
|
||||
self.storages = OrderedDict()
|
||||
app_configs = apps.get_app_configs()
|
||||
if app_names:
|
||||
app_names = set(app_names)
|
||||
app_configs = [ac for ac in app_configs if ac.name in app_names]
|
||||
for app_config in app_configs:
|
||||
app_storage = self.storage_class(
|
||||
os.path.join(app_config.path, self.source_dir))
|
||||
if os.path.isdir(app_storage.location):
|
||||
self.storages[app_config.name] = app_storage
|
||||
if app_config.name not in self.apps:
|
||||
self.apps.append(app_config.name)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def list(self, ignore_patterns):
|
||||
"""
|
||||
List all files in all app storages.
|
||||
"""
|
||||
for storage in self.storages.values():
|
||||
if storage.exists(''): # check if storage location exists
|
||||
for path in utils.get_files(storage, ignore_patterns):
|
||||
yield path, storage
|
||||
|
||||
def find(self, path, all=False):
|
||||
"""
|
||||
Look for files in the app directories.
|
||||
"""
|
||||
matches = []
|
||||
for app in self.apps:
|
||||
app_location = self.storages[app].location
|
||||
if app_location not in searched_locations:
|
||||
searched_locations.append(app_location)
|
||||
match = self.find_in_app(app, path)
|
||||
if match:
|
||||
if not all:
|
||||
return match
|
||||
matches.append(match)
|
||||
return matches
|
||||
|
||||
def find_in_app(self, app, path):
|
||||
"""
|
||||
Find a requested static file in an app's static locations.
|
||||
"""
|
||||
storage = self.storages.get(app)
|
||||
if storage:
|
||||
# only try to find a file if the source dir actually exists
|
||||
if storage.exists(path):
|
||||
matched_path = storage.path(path)
|
||||
if matched_path:
|
||||
return matched_path
|
||||
|
||||
|
||||
class BaseStorageFinder(BaseFinder):
|
||||
"""
|
||||
A base static files finder to be used to extended
|
||||
with an own storage class.
|
||||
"""
|
||||
storage = None
|
||||
|
||||
def __init__(self, storage=None, *args, **kwargs):
|
||||
if storage is not None:
|
||||
self.storage = storage
|
||||
if self.storage is None:
|
||||
raise ImproperlyConfigured("The staticfiles storage finder %r "
|
||||
"doesn't have a storage class "
|
||||
"assigned." % self.__class__)
|
||||
# Make sure we have a storage instance here.
|
||||
if not isinstance(self.storage, (Storage, LazyObject)):
|
||||
self.storage = self.storage()
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def find(self, path, all=False):
|
||||
"""
|
||||
Look for files in the default file storage, if it's local.
|
||||
"""
|
||||
try:
|
||||
self.storage.path('')
|
||||
except NotImplementedError:
|
||||
pass
|
||||
else:
|
||||
if self.storage.location not in searched_locations:
|
||||
searched_locations.append(self.storage.location)
|
||||
if self.storage.exists(path):
|
||||
match = self.storage.path(path)
|
||||
if all:
|
||||
match = [match]
|
||||
return match
|
||||
return []
|
||||
|
||||
def list(self, ignore_patterns):
|
||||
"""
|
||||
List all files of the storage.
|
||||
"""
|
||||
for path in utils.get_files(self.storage, ignore_patterns):
|
||||
yield path, self.storage
|
||||
|
||||
|
||||
class DefaultStorageFinder(BaseStorageFinder):
|
||||
"""
|
||||
A static files finder that uses the default storage backend.
|
||||
"""
|
||||
storage = default_storage
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
base_location = getattr(self.storage, 'base_location', empty)
|
||||
if not base_location:
|
||||
raise ImproperlyConfigured("The storage backend of the "
|
||||
"staticfiles finder %r doesn't have "
|
||||
"a valid location." % self.__class__)
|
||||
|
||||
|
||||
def find(path, all=False):
|
||||
"""
|
||||
Find a static file with the given path using all enabled finders.
|
||||
|
||||
If ``all`` is ``False`` (default), return the first matching
|
||||
absolute path (or ``None`` if no match). Otherwise return a list.
|
||||
"""
|
||||
searched_locations[:] = []
|
||||
matches = []
|
||||
for finder in get_finders():
|
||||
result = finder.find(path, all=all)
|
||||
if not all and result:
|
||||
return result
|
||||
if not isinstance(result, (list, tuple)):
|
||||
result = [result]
|
||||
matches.extend(result)
|
||||
if matches:
|
||||
return matches
|
||||
# No match.
|
||||
return [] if all else None
|
||||
|
||||
|
||||
def get_finders():
|
||||
for finder_path in settings.STATICFILES_FINDERS:
|
||||
yield get_finder(finder_path)
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
def get_finder(import_path):
|
||||
"""
|
||||
Import the staticfiles finder class described by import_path, where
|
||||
import_path is the full Python path to the class.
|
||||
"""
|
||||
Finder = import_string(import_path)
|
||||
if not issubclass(Finder, BaseFinder):
|
||||
raise ImproperlyConfigured('Finder "%s" is not a subclass of "%s"' %
|
||||
(Finder, BaseFinder))
|
||||
return Finder()
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles.handlers import StaticFilesHandler
|
||||
from django.core.management.commands.runserver import (
|
||||
Command as RunserverCommand,
|
||||
)
|
||||
|
||||
|
||||
class Command(RunserverCommand):
|
||||
help = "Starts a lightweight Web server for development and also serves static files."
|
||||
|
||||
def add_arguments(self, parser):
|
||||
super().add_arguments(parser)
|
||||
parser.add_argument(
|
||||
'--nostatic', action="store_false", dest='use_static_handler',
|
||||
help='Tells Django to NOT automatically serve static files at STATIC_URL.',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--insecure', action="store_true", dest='insecure_serving',
|
||||
help='Allows serving static files even if DEBUG is False.',
|
||||
)
|
||||
|
||||
def get_handler(self, *args, **options):
|
||||
"""
|
||||
Return the static files serving handler wrapping the default handler,
|
||||
if static files should be served. Otherwise return the default handler.
|
||||
"""
|
||||
handler = super().get_handler(*args, **options)
|
||||
use_static_handler = options['use_static_handler']
|
||||
insecure_serving = options['insecure_serving']
|
||||
if use_static_handler and (settings.DEBUG or insecure_serving):
|
||||
return StaticFilesHandler(handler)
|
||||
return handler
|
||||
@@ -0,0 +1,13 @@
|
||||
from django.contrib.staticfiles.handlers import StaticFilesHandler
|
||||
from django.test import LiveServerTestCase
|
||||
|
||||
|
||||
class StaticLiveServerTestCase(LiveServerTestCase):
|
||||
"""
|
||||
Extend django.test.LiveServerTestCase to transparently overlay at test
|
||||
execution-time the assets provided by the staticfiles app finders. This
|
||||
means you don't need to run collectstatic before or as a part of your tests
|
||||
setup.
|
||||
"""
|
||||
|
||||
static_handler = StaticFilesHandler
|
||||
@@ -0,0 +1,19 @@
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib.staticfiles.views import serve
|
||||
|
||||
urlpatterns = []
|
||||
|
||||
|
||||
def staticfiles_urlpatterns(prefix=None):
|
||||
"""
|
||||
Helper function to return a URL pattern for serving static files.
|
||||
"""
|
||||
if prefix is None:
|
||||
prefix = settings.STATIC_URL
|
||||
return static(prefix, view=serve)
|
||||
|
||||
|
||||
# Only append if urlpatterns are empty
|
||||
if settings.DEBUG and not urlpatterns:
|
||||
urlpatterns += staticfiles_urlpatterns()
|
||||
@@ -0,0 +1,63 @@
|
||||
import fnmatch
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
|
||||
def matches_patterns(path, patterns=None):
|
||||
"""
|
||||
Return True or False depending on whether the ``path`` should be
|
||||
ignored (if it matches any pattern in ``ignore_patterns``).
|
||||
"""
|
||||
return any(fnmatch.fnmatchcase(path, pattern) for pattern in (patterns or []))
|
||||
|
||||
|
||||
def get_files(storage, ignore_patterns=None, location=''):
|
||||
"""
|
||||
Recursively walk the storage directories yielding the paths
|
||||
of all files that should be copied.
|
||||
"""
|
||||
if ignore_patterns is None:
|
||||
ignore_patterns = []
|
||||
directories, files = storage.listdir(location)
|
||||
for fn in files:
|
||||
# Match only the basename.
|
||||
if matches_patterns(fn, ignore_patterns):
|
||||
continue
|
||||
if location:
|
||||
fn = os.path.join(location, fn)
|
||||
# Match the full file path.
|
||||
if matches_patterns(fn, ignore_patterns):
|
||||
continue
|
||||
yield fn
|
||||
for dir in directories:
|
||||
if matches_patterns(dir, ignore_patterns):
|
||||
continue
|
||||
if location:
|
||||
dir = os.path.join(location, dir)
|
||||
yield from get_files(storage, ignore_patterns, dir)
|
||||
|
||||
|
||||
def check_settings(base_url=None):
|
||||
"""
|
||||
Check if the staticfiles settings have sane values.
|
||||
"""
|
||||
if base_url is None:
|
||||
base_url = settings.STATIC_URL
|
||||
if not base_url:
|
||||
raise ImproperlyConfigured(
|
||||
"You're using the staticfiles app "
|
||||
"without having set the required STATIC_URL setting.")
|
||||
if settings.MEDIA_URL == base_url:
|
||||
raise ImproperlyConfigured("The MEDIA_URL and STATIC_URL "
|
||||
"settings must have different values")
|
||||
if (settings.DEBUG and settings.MEDIA_URL and settings.STATIC_URL and
|
||||
settings.MEDIA_URL.startswith(settings.STATIC_URL)):
|
||||
raise ImproperlyConfigured(
|
||||
"runserver can't serve media if MEDIA_URL is within STATIC_URL."
|
||||
)
|
||||
if ((settings.MEDIA_ROOT and settings.STATIC_ROOT) and
|
||||
(settings.MEDIA_ROOT == settings.STATIC_ROOT)):
|
||||
raise ImproperlyConfigured("The MEDIA_ROOT and STATIC_ROOT "
|
||||
"settings must have different values")
|
||||
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
Views and functions for serving static files. These are only to be used during
|
||||
development, and SHOULD NOT be used in a production setting.
|
||||
|
||||
"""
|
||||
import os
|
||||
import posixpath
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.http import Http404
|
||||
from django.views import static
|
||||
|
||||
|
||||
def serve(request, path, insecure=False, **kwargs):
|
||||
"""
|
||||
Serve static files below a given point in the directory structure or
|
||||
from locations inferred from the staticfiles finders.
|
||||
|
||||
To use, put a URL pattern such as::
|
||||
|
||||
from django.contrib.staticfiles import views
|
||||
|
||||
url(r'^(?P<path>.*)$', views.serve)
|
||||
|
||||
in your URLconf.
|
||||
|
||||
It uses the django.views.static.serve() view to serve the found files.
|
||||
"""
|
||||
if not settings.DEBUG and not insecure:
|
||||
raise Http404
|
||||
normalized_path = posixpath.normpath(path).lstrip('/')
|
||||
absolute_path = finders.find(normalized_path)
|
||||
if not absolute_path:
|
||||
if path.endswith('/') or path == '':
|
||||
raise Http404("Directory indexes are not allowed here.")
|
||||
raise Http404("'%s' could not be found" % path)
|
||||
document_root, path = os.path.split(absolute_path)
|
||||
return static.serve(request, path, document_root=document_root, **kwargs)
|
||||
Reference in new issue
Block a user