mirror of https://github.com/django/django.git
Fixed #19879 -- Have 'findstatic' says on which directories it searched the relative paths.
Added searched_locations in finders module. Added verbosity flag level 2 on 'findstatic' command that will output the directories on which it searched the relative paths. Reported by ccurvey. Initial patch by Jonas Svensson and Vajrasky Kok.
This commit is contained in:
parent
935e6c1dfc
commit
6a9ed7d403
|
@ -12,11 +12,15 @@ from django.utils import six, lru_cache
|
||||||
|
|
||||||
from django.contrib.staticfiles import utils
|
from django.contrib.staticfiles import utils
|
||||||
|
|
||||||
|
# To keep track on which directories the finder has searched the static files.
|
||||||
|
searched_locations = []
|
||||||
|
|
||||||
|
|
||||||
class BaseFinder(object):
|
class BaseFinder(object):
|
||||||
"""
|
"""
|
||||||
A base file finder to be used for custom staticfiles finder classes.
|
A base file finder to be used for custom staticfiles finder classes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def find(self, path, all=False):
|
def find(self, path, all=False):
|
||||||
"""
|
"""
|
||||||
Given a relative file path this ought to find an
|
Given a relative file path this ought to find an
|
||||||
|
@ -75,6 +79,8 @@ class FileSystemFinder(BaseFinder):
|
||||||
"""
|
"""
|
||||||
matches = []
|
matches = []
|
||||||
for prefix, root in self.locations:
|
for prefix, root in self.locations:
|
||||||
|
if root not in searched_locations:
|
||||||
|
searched_locations.append(root)
|
||||||
matched_path = self.find_location(root, path, prefix)
|
matched_path = self.find_location(root, path, prefix)
|
||||||
if matched_path:
|
if matched_path:
|
||||||
if not all:
|
if not all:
|
||||||
|
@ -147,6 +153,9 @@ class AppDirectoriesFinder(BaseFinder):
|
||||||
"""
|
"""
|
||||||
matches = []
|
matches = []
|
||||||
for app in self.apps:
|
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)
|
match = self.find_in_app(app, path)
|
||||||
if match:
|
if match:
|
||||||
if not all:
|
if not all:
|
||||||
|
@ -195,6 +204,8 @@ class BaseStorageFinder(BaseFinder):
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
if self.storage.location not in searched_locations:
|
||||||
|
searched_locations.append(self.storage.location)
|
||||||
if self.storage.exists(path):
|
if self.storage.exists(path):
|
||||||
match = self.storage.path(path)
|
match = self.storage.path(path)
|
||||||
if all:
|
if all:
|
||||||
|
@ -232,6 +243,7 @@ def find(path, all=False):
|
||||||
If ``all`` is ``False`` (default), return the first matching
|
If ``all`` is ``False`` (default), return the first matching
|
||||||
absolute path (or ``None`` if no match). Otherwise return a list.
|
absolute path (or ``None`` if no match). Otherwise return a list.
|
||||||
"""
|
"""
|
||||||
|
searched_locations[:] = []
|
||||||
matches = []
|
matches = []
|
||||||
for finder in get_finders():
|
for finder in get_finders():
|
||||||
result = finder.find(path, all=all)
|
result = finder.find(path, all=all)
|
||||||
|
|
|
@ -21,15 +21,25 @@ class Command(LabelCommand):
|
||||||
verbosity = int(options.get('verbosity', 1))
|
verbosity = int(options.get('verbosity', 1))
|
||||||
result = finders.find(path, all=options['all'])
|
result = finders.find(path, all=options['all'])
|
||||||
path = force_text(path)
|
path = force_text(path)
|
||||||
|
if verbosity >= 2:
|
||||||
|
searched_locations = ("Looking in the following locations:\n %s" %
|
||||||
|
"\n ".join(force_text(location)
|
||||||
|
for location in finders.searched_locations))
|
||||||
|
else:
|
||||||
|
searched_locations = ''
|
||||||
if result:
|
if result:
|
||||||
if not isinstance(result, (list, tuple)):
|
if not isinstance(result, (list, tuple)):
|
||||||
result = [result]
|
result = [result]
|
||||||
result = (force_text(os.path.realpath(path)) for path in result)
|
result = (force_text(os.path.realpath(path)) for path in result)
|
||||||
if verbosity >= 1:
|
if verbosity >= 1:
|
||||||
output = '\n '.join(result)
|
file_list = '\n '.join(result)
|
||||||
return "Found '%s' here:\n %s" % (path, output)
|
return ("Found '%s' here:\n %s\n%s" %
|
||||||
|
(path, file_list, searched_locations))
|
||||||
else:
|
else:
|
||||||
return '\n'.join(result)
|
return '\n'.join(result)
|
||||||
else:
|
else:
|
||||||
|
message = ["No matching file found for '%s'." % path]
|
||||||
|
if verbosity >= 2:
|
||||||
|
message.append(searched_locations)
|
||||||
if verbosity >= 1:
|
if verbosity >= 1:
|
||||||
self.stderr.write("No matching file found for '%s'." % path)
|
self.stderr.write('\n'.join(message))
|
||||||
|
|
|
@ -162,6 +162,23 @@ output and just get the path names::
|
||||||
/home/special.polls.com/core/static/css/base.css
|
/home/special.polls.com/core/static/css/base.css
|
||||||
/home/polls.com/core/static/css/base.css
|
/home/polls.com/core/static/css/base.css
|
||||||
|
|
||||||
|
On the other hand, by setting the :djadminopt:`--verbosity` flag to 2, you can
|
||||||
|
get all the directories on which it searched the relative paths::
|
||||||
|
|
||||||
|
$ python manage.py findstatic css/base.css --verbosity 2
|
||||||
|
Found 'css/base.css' here:
|
||||||
|
/home/special.polls.com/core/static/css/base.css
|
||||||
|
/home/polls.com/core/static/css/base.css
|
||||||
|
Looking in the following locations:
|
||||||
|
/home/special.polls.com/core/static
|
||||||
|
/home/polls.com/core/static
|
||||||
|
/some/other/path/static
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
|
The additional message of on which directories it searched the relative
|
||||||
|
paths is new in Django 1.7.
|
||||||
|
|
||||||
.. _staticfiles-runserver:
|
.. _staticfiles-runserver:
|
||||||
|
|
||||||
runserver
|
runserver
|
||||||
|
@ -366,6 +383,23 @@ files:
|
||||||
|
|
||||||
.. _staticfiles-development-view:
|
.. _staticfiles-development-view:
|
||||||
|
|
||||||
|
Finders Module
|
||||||
|
==============
|
||||||
|
|
||||||
|
``staticfiles`` finders has a ``searched_locations`` list with directory paths
|
||||||
|
in which they search for the relative paths. Example usage::
|
||||||
|
|
||||||
|
from django.contrib.staticfiles import finders
|
||||||
|
|
||||||
|
result = finders.find('css/base.css')
|
||||||
|
searched_locations = finders.searched_locations
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
|
The ``get_searched_locations`` function is new in Django 1.7. Previously, we
|
||||||
|
have to check the locations of our :setting:`STATICFILES_FINDERS` manually
|
||||||
|
one by one.
|
||||||
|
|
||||||
Static file development view
|
Static file development view
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
|
@ -1051,6 +1051,10 @@ Miscellaneous
|
||||||
which does allow primary keys with value 0. It only forbids *autoincrement*
|
which does allow primary keys with value 0. It only forbids *autoincrement*
|
||||||
primary keys with value 0.
|
primary keys with value 0.
|
||||||
|
|
||||||
|
* :djadmin:`findstatic` now accepts verbosity flag level 2, meaning it will
|
||||||
|
show the directories on which it searched the relative paths. See
|
||||||
|
:djadmin:`findstatic` for example output.
|
||||||
|
|
||||||
.. _deprecated-features-1.7:
|
.. _deprecated-features-1.7:
|
||||||
|
|
||||||
Features deprecated in 1.7
|
Features deprecated in 1.7
|
||||||
|
|
|
@ -223,6 +223,35 @@ class TestFindStatic(CollectionTestCase, TestDefaults):
|
||||||
self.assertIn('project', force_text(lines[0]))
|
self.assertIn('project', force_text(lines[0]))
|
||||||
self.assertIn('apps', force_text(lines[1]))
|
self.assertIn('apps', force_text(lines[1]))
|
||||||
|
|
||||||
|
def test_all_files_more_verbose(self):
|
||||||
|
"""
|
||||||
|
Test that findstatic returns all candidate files if run without --first and -v2.
|
||||||
|
Also, test that findstatic returns the searched locations with -v2.
|
||||||
|
"""
|
||||||
|
out = six.StringIO()
|
||||||
|
call_command('findstatic', 'test/file.txt', verbosity=2, stdout=out)
|
||||||
|
out.seek(0)
|
||||||
|
lines = [l.strip() for l in out.readlines()]
|
||||||
|
self.assertIn('project', force_text(lines[1]))
|
||||||
|
self.assertIn('apps', force_text(lines[2]))
|
||||||
|
self.assertIn("Looking in the following locations:", force_text(lines[3]))
|
||||||
|
searched_locations = ', '.join(lines[4:])
|
||||||
|
#AppDirectoriesFinder searched locations
|
||||||
|
self.assertIn(os.path.join('staticfiles_tests', 'apps', 'test', 'static'),
|
||||||
|
searched_locations)
|
||||||
|
self.assertIn(os.path.join('staticfiles_tests', 'apps', 'no_label', 'static'),
|
||||||
|
searched_locations)
|
||||||
|
self.assertIn(os.path.join('django', 'contrib', 'admin', 'static'),
|
||||||
|
searched_locations)
|
||||||
|
self.assertIn(os.path.join('django', 'tests', 'servers', 'another_app', 'static'),
|
||||||
|
searched_locations)
|
||||||
|
#FileSystemFinder searched locations
|
||||||
|
self.assertIn(TEST_SETTINGS['STATICFILES_DIRS'][1][1], searched_locations)
|
||||||
|
self.assertIn(TEST_SETTINGS['STATICFILES_DIRS'][0], searched_locations)
|
||||||
|
#DefaultStorageFinder searched locations
|
||||||
|
self.assertIn(os.path.join('staticfiles_tests', 'project', 'site_media', 'media'),
|
||||||
|
searched_locations)
|
||||||
|
|
||||||
|
|
||||||
class TestConfiguration(StaticFilesTestCase):
|
class TestConfiguration(StaticFilesTestCase):
|
||||||
def test_location_empty(self):
|
def test_location_empty(self):
|
||||||
|
@ -779,6 +808,9 @@ class TestDefaultStorageFinder(StaticFilesTestCase, FinderTestCase):
|
||||||
self.find_all = ('media-file.txt', [test_file_path])
|
self.find_all = ('media-file.txt', [test_file_path])
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(STATICFILES_FINDERS=
|
||||||
|
('django.contrib.staticfiles.finders.FileSystemFinder',),
|
||||||
|
STATICFILES_DIRS=[os.path.join(TEST_ROOT, 'project', 'documents')])
|
||||||
class TestMiscFinder(TestCase):
|
class TestMiscFinder(TestCase):
|
||||||
"""
|
"""
|
||||||
A few misc finder tests.
|
A few misc finder tests.
|
||||||
|
@ -805,6 +837,11 @@ class TestMiscFinder(TestCase):
|
||||||
self.assertEqual(cache_info.hits, 9)
|
self.assertEqual(cache_info.hits, 9)
|
||||||
self.assertEqual(cache_info.currsize, 1)
|
self.assertEqual(cache_info.currsize, 1)
|
||||||
|
|
||||||
|
def test_searched_locations(self):
|
||||||
|
finders.find('spam')
|
||||||
|
self.assertEqual(finders.searched_locations,
|
||||||
|
[os.path.join(TEST_ROOT, 'project', 'documents')])
|
||||||
|
|
||||||
@override_settings(STATICFILES_DIRS='a string')
|
@override_settings(STATICFILES_DIRS='a string')
|
||||||
def test_non_tuple_raises_exception(self):
|
def test_non_tuple_raises_exception(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue