Integrates the webassets library with Django, adding support for merging, minifying and compiling CSS and Javascript files.
- Documentation:
- https://django-assets.readthedocs.io/
Django webassets integration.
License: BSD 2-Clause "Simplified" License
Integrates the webassets library with Django, adding support for merging, minifying and compiling CSS and Javascript files.
/usr/lib/python3.8/site-packages/django_assets/glob.py:124: DeprecationWarning:
invalid escape sequence \Z
Hi,
Lately I'm receiving lots of BundleError
exceptions because the underlying files django-assets is trying to read don't exist apparently (IOError
is raised). The source files defined in the bundles do exist though, as well as the merged bundles.
For example, I have defined a bundle like this:
css_common = Bundle(
'css/style.css', 'css/fancybox.css', 'css/tipsy.css',
'css/markup.css', 'css/sprite.css', 'css/select2.css',
filters='cssmin', output='css/common.min.css')
register('css_common', css_common)
And referenced it in the templates:
{% assets "css_common" %}
<link rel="stylesheet" type="text/css" href="{{ ASSET_URL }}" />
{% endassets %}
All works fine so far and I can even confirm it from a manage.py shell
session:
In [1]: from myapp.assets import css_common
In [2]: css_common.urls()
Out[2]: ['/assets/css/common.min.css?5e87f161']
In [3]: css_common
Out[3]: <Bundle output=css/common.min.css, filters=[<webassets.filter.cssmin.CSSMin object at 0xa7b610c>], contents=('css/style.css', 'css/fancybox.css', 'css/tipsy.css', 'css/markup.css', 'css/sprite.css', 'css/select2.css')>
In [4]: from django_assets import env
In [5]: env.get_env()['css_common']
Out[5]: <Bundle output=css/common.min.css, filters=[<webassets.filter.cssmin.CSSMin object at 0xa7b610c>], contents=('css/style.css', 'css/fancybox.css', 'css/tipsy.css', 'css/markup.css', 'css/sprite.css', 'css/select2.css')>
On the other hand, from the tracebacks I can see the bundle is not being properly populated with the expected contents:
<Bundle output=None, filters=(), contents=(u'css_common',)>
After analyzing webassets' and django-assets' source code, I suspect the environment isn't being properly set and instead it treats the bundle identifier as a filename, therefore raising IOError
at a later stage.
This seems to happen when visiting a non-existent URL and a 404 page is returned. Any relevant settings that might affect this are set to False
, such as DEBUG
, ASSETS_DEBUG
, and ASSETS_AUTO_BUILD
The current documentation misleads that django-assets will work with Django and Jinja2. It will not, not out of the box at least.
'webassets'
and 'django_assets'
to INSTALLED_APPS
'django_jinja.backend.Jinja2'
(or 'django.template.backends.jinja2'
) to TEMPLATES
'webassets.ext.jinja2.AssetsExtension'
to Jinja2 extensions{% assets "js/main.js", output="min/main.js" %}{% endassets %}
to your template fileFile "/Users/semenov/test/var/venv/lib/python3.5/site-packages/webassets/ext/jinja2.py" in _render_assets
Exception Type: RuntimeError at /test/
Exception Value: No assets environment configured in Jinja2 environment
The environment should be automatically configured; or it should be clearly documented how to configure it manually.
Create a custom extension:
# myapp/jinja2_assets.py
from jinja2.ext import Extension
from django_assets.env import get_env
class AssetsExtension(Extension):
def __init__(self, environment):
super().__init__(environment)
environment.assets_environment = get_env()
then add myapp.jinja2_assets.AssetsExtension
to the list of Jinja2 extensions.
Create a bundle that uses globs:
js = Bundle('js/*.js')
And say it includes 4 files, the final output will be:
<script src="http://localhost/static/js/*.js"></script>
<script src="http://localhost/static/js/*.js"></script>
<script src="http://localhost/static/js/*.js"></script>
<script src="http://localhost/static/js/*.js"></script>
The problem stems from DjangoResolver#resolve_source_to_url
only using the item
argument, which is the unexpanded glob pattern, rather then making a url from the filepath
argument which is the expanded path.
https://github.com/miracle2k/django-assets/blob/master/django_assets/env.py#L153-L161
I would submit a PR, but I'm not sure of the best way to go around fixing this.
Is it possible to have the automatic rebuild of the assets running on ./manage.py runserver
?
See also http://webassets.readthedocs.io/en/latest/script.html#watch , CC @userzimmermann
New in Django 4.1, both tests for TestLoader
now fail.
[ 89s] =================================== FAILURES ===================================
[ 89s] _______________________________ TestLoader.test ________________________________
[ 89s]
[ 89s] self = <tests.test_django.TestLoader object at 0x7f14534eebb0>
[ 89s]
[ 90s] def test(self):
[ 90s] > bundles = self.loader.load_bundles()
[ 90s]
[ 90s] tests/test_django.py:192:
[ 90s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 90s] ../../BUILDROOT/python-django-assets-2.0-7.8.x86_64/usr/lib/python3.8/site-packages/django_assets/loaders.py:79: in load_bundles
[ 90s] bundles.extend(self.with_file(filename, self._parse) or [])
[ 90s] /usr/lib/python3.8/site-packages/webassets/loaders.py:333: in with_file
[ 90s] return then_run(filename, contents)
[ 90s] ../../BUILDROOT/python-django-assets-2.0-7.8.x86_64/usr/lib/python3.8/site-packages/django_assets/loaders.py:110: in _parse
[ 90s] for node in t: # don't move into _recurse_node, ``Template`` has a .nodelist attribute
[ 90s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 90s]
[ 90s] self = <Template template_string="b'\n {% l...">
[ 90s]
[ 90s] def __iter__(self):
[ 90s] for node in self.nodelist:
[ 90s] > yield from node
[ 90s] E TypeError: 'TextNode' object is not iterable
[ 90s]
[ 90s] /usr/lib/python3.8/site-packages/django/template/base.py:158: TypeError
[ 90s] ________________________ TestLoader.test_cached_loader _________________________
[ 90s]
[ 90s] self = <tests.test_django.TestLoader object at 0x7f14534ee730>
[ 90s]
[ 90s] def test_cached_loader(self):
[ 90s] settings.TEMPLATE_LOADERS = (
[ 90s] ('django.template.loaders.cached.Loader', (
[ 90s] 'django.template.loaders.filesystem.Loader',
[ 90s] )),
[ 90s] )
[ 90s] > bundles = self.loader.load_bundles()
[ 90s]
[ 90s] tests/test_django.py:202:
[ 90s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 90s] ../../BUILDROOT/python-django-assets-2.0-7.8.x86_64/usr/lib/python3.8/site-packages/django_assets/loaders.py:79: in load_bundles
[ 90s] bundles.extend(self.with_file(filename, self._parse) or [])
[ 90s] /usr/lib/python3.8/site-packages/webassets/loaders.py:333: in with_file
[ 90s] return then_run(filename, contents)
[ 90s] ../../BUILDROOT/python-django-assets-2.0-7.8.x86_64/usr/lib/python3.8/site-packages/django_assets/loaders.py:110: in _parse
[ 90s] for node in t: # don't move into _recurse_node, ``Template`` has a .nodelist attribute
[ 90s] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
[ 90s]
[ 90s] self = <Template template_string="b'\n {% l...">
[ 90s]
[ 90s] def __iter__(self):
[ 90s] for node in self.nodelist:
[ 90s] > yield from node
[ 90s] E TypeError: 'TextNode' object is not iterable
[ 90s]
[ 90s] /usr/lib/python3.8/site-packages/django/template/base.py:158: TypeError
When I try to {% load assets %}
in a template, I get the following error:
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 73, in super
return mark_safe(self.render(self.context))
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/django/template/loader_tags.py", line 63, in render
result = block.nodelist.render(context)
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/django/template/base.py", line 830, in render
bit = self.render_node(node, context)
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/django/template/debug.py", line 74, in render_node
return node.render(context)
File "/home/chris/washwatch/washwatch/django/website/.ve/src/django-assets/django_assets/templatetags/assets.py", line 71, in render
for url in bundle.urls(env=get_env()):
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/webassets/bundle.py", line 685, in urls urls.extend(bundle._urls(env, extra_filters, *args, **kwargs))
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/webassets/bundle.py", line 647, in _urls
*args, **kwargs)
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/webassets/bundle.py", line 494, in _build
if env.updater else True
File "/home/chris/washwatch/washwatch/django/website/.ve/local/lib/python2.7/site-packages/webassets/env.py", line 589, in get_updater
updater = get_updater(self.config['updater'])
File "/home/chris/washwatch/washwatch/django/website/.ve/src/django-assets/django_assets/env.py", line 69, in __getitem__
self._transform_key(key))
KeyError: "Django settings doesn't define ASSETS_UPDATER"
What is this mysterious setting ASSETS_UPDATER
? What are the valid values? I can't see anything about it in the documentation, and the release notes for webassets 0.10
only say that I'm not allowed to set it to False
any more. Fine, so what am I allowed to set it to?
Curious to hear thoughts on using Django's caching framework for manifests. Looks like it would be pretty straightforward. Just need to implement DjangoCache
as a subclass of webassets.cache.BaseCache
.
One question is how to configure it. We could just have ASSETS_CACHE
be set to the DjangoCache
class, which should work as it would be passed through to webassets
. Configuring this way feels a bit clunky though.
In Django 3.0.1 there is a DeprecationWarning with the imp module in the env.py file.
django_assets\env.py:1: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
I would be very happy about a fix :)
Greetings
Using the current django-assets release in master (0.11), when running ./manage.py assets build --parse-templates
, we get a crash that leads to the trace that concludes with:
File "/go/src/github.com/opsmatic/admini-future/.virtualenv/local/lib/python2.7/site-packages/django_assets/loaders.py", line 63, in get_django_template_dirs
from django.template.loaders.app_directories import app_template_dirs
ImportError: cannot import name app_template_dirs
Indeed, app_template_dirs
is MIA in 1.8 (testing with 1.8.5 and newer).
I've got a PR I'll submit with a super simple patch that got us going again.
From the 1.8 release notes - https://docs.djangoproject.com/en/1.9/releases/1.8/#extending-management-command-arguments-through-command-option-list:
Management commands now use argparse instead of optparse to parse command-line arguments passed to commands. This also means that the way to add custom arguments to commands has changed: instead of extending the option_list class list, you should now override the add_arguments() method and add arguments through argparse.add_argument().
Using Django from git results in a traceback:
Traceback (most recent call last):
File "./manage.py", line 25, in <module>
execute_from_command_line(sys.argv)
File "/home/myproject/.virtualenvs/myproject/src/django/django/core/management/__init__.py", line 349, in execute_from_command_line
utility.execute()
File "/home/myproject/.virtualenvs/myproject/src/django/django/core/management/__init__.py", line 341, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/myproject/.virtualenvs/myproject/src/django/django/core/management/__init__.py", line 193, in fetch_command
klass = load_command_class(app_name, subcommand)
File "/home/myproject/.virtualenvs/myproject/src/django/django/core/management/__init__.py", line 40, in load_command_class
module = import_module('%s.management.commands.%s' % (app_name, name))
File "/home/myproject/.virtualenvs/myproject/lib/python3.4/importlib/__init__.py", line 109, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1129, in _exec
File "<frozen importlib._bootstrap>", line 1471, in exec_module
File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
File "/home/myproject/.virtualenvs/myproject/src/django-assets/django_assets/management/commands/assets.py", line 94, in <module>
class Command(BaseCommand):
File "/home/myproject/.virtualenvs/myproject/src/django-assets/django_assets/management/commands/assets.py", line 95, in Command
option_list = BaseCommand.option_list + (
AttributeError: type object 'BaseCommand' has no attribute 'option_list'
Thanks for django-assets! Is there currently any way to define settings such as UGLIFYJS_EXTRA_ARGS
in the Django settings file?
Currently, it's not possible for my own project's setup.py to require webassets 0.9 and django-assets.
This is because django-assets ties itself to the corresponding webassets, and there is no corresponding released django-assets. (I'd expect similar applies to flask-assets)
webassets has been bumped to 0.11.1, and testing with pytest now complains if you have this installed along with django-assets 0.11.
Here https://django-assets.readthedocs.io/en/latest/jinja2.html the link to More exhaustive documentation of the Jinja2 tag points to incorrect location.
Current link: http://elsdoerfer.name/docs/webassets/integration/jinja2.html
Proper location: http://webassets.readthedocs.io/en/latest/integration/jinja2.html
Hi,
just wondering if at some point, generating the .js.map files will be supported with this library ? It could be very handy.
Cheers
Hey, I can't run the package's unit tests, it looks like there are missing files :
$ python setup.py test
[...]
======================================================================
ERROR: tests.test_django.TestStaticFiles.test_build
Finders are used to find source files.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/me/devel/django-assets/tests/test_django.py", line 278, in test_build
self.mkbundle('file1', 'file2', output="out").build()
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 563, in build
disable_cache=disable_cache))
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 498, in _build
force, disable_cache=disable_cache, extra_filters=extra_filters)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 355, in _merge_and_apply
resolved_contents = self.resolve_contents(env, force=True)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 148, in resolve_contents
raise BundleError(e)
BundleError: 'file1' not found (using staticfiles finders)
======================================================================
ERROR: tests.test_django.TestStaticFiles.test_css_rewrite
Test that the cssrewrite filter can deal with staticfiles.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/me/devel/django-assets/tests/test_django.py", line 332, in test_css_rewrite
self.mkbundle('css', filters='cssrewrite', output="out").build()
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 563, in build
disable_cache=disable_cache))
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 498, in _build
force, disable_cache=disable_cache, extra_filters=extra_filters)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 355, in _merge_and_apply
resolved_contents = self.resolve_contents(env, force=True)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 148, in resolve_contents
raise BundleError(e)
BundleError: 'css' not found (using staticfiles finders)
======================================================================
ERROR: tests.test_django.TestStaticFiles.test_find_with_glob
Globs can be used across staticdirs.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/me/devel/django-assets/tests/test_django.py", line 298, in test_find_with_glob
self.mkbundle('file?', output="out").build()
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 563, in build
disable_cache=disable_cache))
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 498, in _build
force, disable_cache=disable_cache, extra_filters=extra_filters)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 355, in _merge_and_apply
resolved_contents = self.resolve_contents(env, force=True)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 148, in resolve_contents
raise BundleError(e)
BundleError: 'file?' not found (using staticfiles finders)
======================================================================
ERROR: tests.test_django.TestStaticFiles.test_find_with_recursive_glob
Recursive globs.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/me/devel/django-assets/tests/test_django.py", line 304, in test_find_with_recursive_glob
self.mkbundle('**/*.js', output="out").build()
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 563, in build
disable_cache=disable_cache))
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 498, in _build
force, disable_cache=disable_cache, extra_filters=extra_filters)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 355, in _merge_and_apply
resolved_contents = self.resolve_contents(env, force=True)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 148, in resolve_contents
raise BundleError(e)
BundleError: '**/*.js' not found (using staticfiles finders)
======================================================================
ERROR: tests.test_django.TestStaticFiles.test_serve_built_files
The files we write to STATIC_ROOT are served in debug mode
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/me/devel/django-assets/tests/test_django.py", line 318, in test_serve_built_files
self.mkbundle('file1', 'file2', output="out").build()
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 563, in build
disable_cache=disable_cache))
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 498, in _build
force, disable_cache=disable_cache, extra_filters=extra_filters)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 355, in _merge_and_apply
resolved_contents = self.resolve_contents(env, force=True)
File "/usr/lib/python2.7/site-packages/webassets/bundle.py", line 148, in resolve_contents
raise BundleError(e)
BundleError: 'file1' not found (using staticfiles finders)
----------------------------------------------------------------------
Ran 20 tests in 0.197s
FAILED (errors=5)
Hola! @netpastor has created a ZenHub account for the miracle2k organization. ZenHub is the leading team collaboration and project management solution built for GitHub.
To get set up with ZenHub, all you have to do is download the browser extension and log in with your GitHub account. Once you do, you’ll get access to ZenHub’s complete feature-set immediately.
ZenHub adds a series of enhancements directly inside the GitHub UI:
Still curious? See more ZenHub features or read user reviews. This issue was written by your friendly ZenHub bot, posted by request from @netpastor.
Apologies in advance of the lack of detail in this issue, but as you'll see I don't have much!
On Friday I deployed a version of our app, only to find that certain sections of our site caused our app to hang; and once hung only a restart of the app could recover it. A carpet-bombing of debug statement later it appears that the problem was caused by any template that included the {% assets %}
instruction. This was a new problem (and we deploy multiple times a day) that only began yesterday. Further investigation showed that we were including the latest build in our deployment using the pip '-e' flag, which suggests that the problem lies the 08407c4 commit.
The symptoms were simple - a complete lack of logging / debug output, but a consistent (and repeatable) timeout from our reverse proxy (which cut the connection at 30s). It just died. And once dead, would not recover. Looking at the commit, it seems like something happens on a separate thread that gets stuck.
Some details:
The output from our Heroku instance:
2013-10-27 09:08:49.891 269 <158>1 2013-10-27T09:08:49.358189+00:00 heroku router - - at=error code=H12 desc="Request timeout" method=GET path=/ host=[redacted].herokuapp.com fwd="2.102.222.71" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0
The issue was solved by fixing the deployment to v0.8 of django-assets in our requirements.txt
:
django-assets==0.8
instead of
-e git://github.com/miracle2k/django-assets.git#egg=django-assets
Sorry for not having any more detail on exactly what the problem was, but I can confirm that this behaviour can be reproduced locally (running on Ubuntu 12.04, 64-bit,running on VirtualBox as a Vagrant VM).
In terms of timing, this is the output from running heroku releases
on our affected app:
v214 Deploy b82f8be [email protected] 2013/10/27 17:56:22 <-- FIXED
v213 Rollback to v211 [email protected] 2013/10/26 12:09:01
v212 Deploy 4dc11fe [email protected] 2013/10/26 12:00:29 <-- DOES NOT WORK
v211 Deploy 6a60784 [email protected] 2013/10/25 09:56:19
The problem occurred in deployment 4dc11fe
, which we immediately rolled back to 6a6o784
.
Hello there,
I have noticed a problem and limitation with django-assets which I'm hoping you can help me with.
Limitation: I would like to store my assets in an "assets" directory and generate output in the usual STATIC_ROOT directory. With flask-assets, this could be done by using the ASSETS_LOAD_PATH config item, is there a way to do this with Django?
Problem: The collectstatic command also collects the original asset source code into my final static directory. Django Compressor uses the following workaround to prevent this:
from compressor.utils import staticfiles
from compressor.storage import CompressorFileStorage
class CompressorFinder(staticfiles.finders.BaseStorageFinder):
"""
A staticfiles finder that looks in COMPRESS_ROOT
for compressed files, to be used during development
with staticfiles development file server or during
deployment.
"""
storage = CompressorFileStorage
def list(self, ignore_patterns):
return []
An empty list is returned for the list command.
Please let me know your thoughts :)
There are a couple issues we're seeing with the way django-assets has decided to integrate with webassets.
The relationship with collectstatic
is especially confusing. By django's definition, collectstatic
places the static files in the location that they will be served, so if you're using a CDN, this location is remote. assets build
expects collectstatic
to have been called, placing the files in the ASSETS_ROOT
, and cannot (and shouldn't) build from a remote location. If we have collectstatic
drop the files on the file system, assets build
will work, but then there's no integrated way to upload to s3.
The other issue is with a remote manifest. Once we run assets build
the manifest is updated, but the files haven't been uploaded, which causes pages to request compiled assets that don't yet exist.
There are two possible changes I can think of to fix this
staticfinders
so collect static assets. collectstatic
can then be used to upload to s3. This doesn't totally solve the remote manifest, but that can be fixed by running assets build
with a dummy manifest, then collectstatic
, then assets build
again to update the manifest.collectstatic
to place the files in the correct directory and then have assets build
honor django STATICFILES_STORAGES
to upload the files before updating the manifest. This obviously means changes in webassets as well.It looks like this has all been discussed here:
Let me know if I'm missing anything.
How do you think this would best be fixed?
Instead of
{% assets filters="jsmin", output="gen/packed.js", "common/jquery.js", "site/base.js", "site/widgets.js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
it would be better if we could just do
{% assetsjs filters="jsmin", output="gen/packed.js", "common/jquery.js", "site/base.js", "site/widgets.js" %}
It could even detect that it is a js file, so we wouldn't have to have different asset tags like assetscss etc.
Here is a simple implementation that could be improved:
class JsCssAssetsNode(AssetsNode):
def render(self, context):
bundle = self.resolve(context)
result = u""
for url in bundle.urls(env=get_env()):
result += self.template.format(ASSET_URL=url)
return result
class JsAssetsNode(JsCssAssetsNode):
template = '<script type="text/javascript" src="{ASSET_URL}"></script>'
class CssAssetsNode(JsCssAssetsNode):
template = '<link rel="stylesheet" type="text/css" href="{ASSET_URL}" media="all" />'
def assets(parser, token, type=""):
filters = None
output = None
debug = None
files = []
# parse the arguments
args = token.split_contents()[1:]
for arg in args:
# Handle separating comma; for backwards-compatibility
# reasons, this is currently optional, but is enforced by
# the Jinja extension already.
if arg[-1] == ',':
arg = arg[:-1]
if not arg:
continue
# determine if keyword or positional argument
arg = arg.split('=', 1)
if len(arg) == 1:
name = None
value = arg[0]
else:
name, value = arg
# handle known keyword arguments
if name == 'output':
output = value
elif name == 'debug':
debug = value
elif name == 'filters':
filters = value
elif name == 'filter':
filters = value
warnings.warn('The "filter" option of the {% assets %} '
'template tag has been renamed to '
'"filters" for consistency reasons.',
ImminentDeprecationWarning)
# positional arguments are source files
elif name is None:
files.append(value)
else:
raise template.TemplateSyntaxError('Unsupported keyword argument "%s"'%name)
# capture until closing tag
childnodes = parser.parse(("endassets" + type,))
parser.delete_first_token()
if type == "":
return AssetsNode(filters, output, debug, files, childnodes)
elif type == "js":
return JsAssetsNode(filters, output, debug, files, childnodes)
elif type == "css":
return CssAssetsNode(filters, output, debug, files, childnodes)
# expose the default Django tag
register.tag('assets', assets)
register.tag('assetsjs', functools.partial(assets, type='js'))
register.tag('assetscss', functools.partial(assets, type='css'))
I'm using Django 1.11 with Whitenoise, and build my assets with:
./manage.py collectstatic
./manage.py assets build --manifest django
Built assets are correctly added to the staticfiles.json manifest.
IF I use the version of the file in the query string, the file is served but Whitenoise does not add far into the future cache headers:
✗ curl -I "http://localhost:8000/static/gen/packed.js?84fed0ca" 2>/dev/null |grep -i cache
Cache-Control: max-age=60, public
When I use the version placeholder:
output='gen/packed.%(version)s.js',
I get an error when trying to render the template:
webassets.exceptions.BundleError: Cannot find version of <Bundle output=gen/packed.%(version)s.js, filters=[<webassets.filter.jsmin.JSMin object at 0x106d45cf8>], contents=('js/vendor/jquery/jquery.min.js', 'js/vendor/bootstrap/bootstrap.min.js', 'js/main.js')>. There is no manifest which knows the version, and it cannot be determined dynamically, because: output target has a placeholder
Versions:
django-assets==0.12
webassets==0.12.1
Hi I just discovered this issue with Django 1.4.2 and using staticfiles.
In the file django_assets.env line 279 :
import_module("%s" % module)
module is a list() in my case containing something like:
ASSETS_MODULES = [
"myproject.assets"
]
according to the documentation.
The problem is that "import_module" takes a string as argument and in this case the result of :
("%s" % module ) is "['myproject.assets']" which is absolutely not a valid module name.
it should be "myproject.assets". You can not pass a list() to import_module(). So you should correct the documentation.
cheers
Settings like UGLIFY_JS_EXTRA_ARGS
don't appear to be working. After a quick browse through the code, it looks like these were never implemented. If that's the case, I'm happy to do that and submit a pull request.
I would suggest using a dictionary such as ASSETS_OPTIONS
to avoid polluting the rest of the settings file.
I'm trying to upgrade to Django 1.10 and django-assets
is one of the libraries I have that doesn't advertise support for it. I tried running its tests on top of #86 with the following patch, but got the below failures. Test compatibility here seems to be around the settings used, which need updating to use TEMPLATES
, but also maybe some stuff needs doing in webassets
too to fix the failures seen in #86?
patch:
diff --git a/tox.ini b/tox.ini
index 5fc998d..0685dde 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,7 @@
[tox]
-envlist = django18-{py27,py33,py34,pypy}, django19-{py27,py34,py35}
+envlist = django18-{py27,py33,py34,pypy},
+ django19-{py27,py34,py35},
+ django110-{py27,py34,py35}
[testenv]
@@ -12,3 +14,4 @@ deps =
https://github.com/miracle2k/webassets/archive/master.tar.gz
django18: Django>=1.8,<1.9
django19: Django>=1.9,<1.10
+ django110: Django>=1.10,<1.11
failures:
django110-py35 create: /Users/adamj/Documents/Projects/django-assets/.tox/django110-py35
django110-py35 installdeps: nose==1.3.7, ipdb>=0.8.0, https://github.com/miracle2k/webassets/archive/master.tar.gz, Django>=1.10,<1.11
django110-py35 inst: /Users/adamj/Documents/Projects/django-assets/.tox/dist/django-assets-0.12.zip
django110-py35 installed: appnope==0.1.0,decorator==4.0.10,Django==1.10.2,django-assets==0.12,ipdb==0.10.1,ipython==5.1.0,ipython-genutils==0.1.0,nose==1.3.7,pexpect==4.2.1,pickleshare==0.7.4,prompt-toolkit==1.0.7,ptyprocess==0.5.1,Pygments==2.1.3,simplegeneric==0.8.1,six==1.10.0,traitlets==4.3.1,wcwidth==0.1.7,webassets==0.12.0
django110-py35 runtests: PYTHONHASHSEED='383892742'
django110-py35 runtests: commands[0] | nosetests
..EFF.......EEEEEEE
======================================================================
ERROR: tests.test_django.TestFilter.test_template
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 312, in test_template
filters=get_filter('template', context={'num': 23232323}),
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/webassets/bundle.py", line 663, in build
disable_cache=disable_cache))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/webassets/bundle.py", line 600, in _build
force, disable_cache=disable_cache, extra_filters=extra_filters)
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/webassets/bundle.py", line 524, in _merge_and_apply
kwargs=item_data)
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/webassets/merge.py", line 276, in apply
return self._wrap_cache(key, func)
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/webassets/merge.py", line 218, in _wrap_cache
content = func().getvalue()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/webassets/merge.py", line 251, in func
getattr(filter, type)(data, out, **kwargs_final)
File "/Users/adamj/Documents/Projects/django-assets/django_assets/filter.py", line 24, in input
t = Template(_in.read(), origin='django-assets', name=source_path)
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
ERROR: tests.test_django.TestTemplateTag.test_debug_option
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 148, in test_debug_option
self.render_template('"file", debug="true"')
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 129, in render_template
return Template('{% load assets %}{% assets '+args+' %}{{ ASSET_URL }};{% endassets %}').render(Context(ctx))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
ERROR: Ensure the tag correcly spits out the urls the bundle returns.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 164, in test_output_urls
assert self.render_template('"file1" "file2" "file3"') == 'foo;bar;'
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 129, in render_template
return Template('{% load assets %}{% assets '+args+' %}{{ ASSET_URL }};{% endassets %}').render(Context(ctx))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
ERROR: tests.test_django.TestTemplateTag.test_reference_bundles
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 132, in test_reference_bundles
self.render_template('"foo_bundle", "bar_bundle"')
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 129, in render_template
return Template('{% load assets %}{% assets '+args+' %}{{ ASSET_URL }};{% endassets %}').render(Context(ctx))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
ERROR: tests.test_django.TestTemplateTag.test_reference_files
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 136, in test_reference_files
self.render_template('"file1", "file2", "file3"')
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 129, in render_template
return Template('{% load assets %}{% assets '+args+' %}{{ ASSET_URL }};{% endassets %}').render(Context(ctx))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
ERROR: tests.test_django.TestTemplateTag.test_reference_mixed
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 140, in test_reference_mixed
self.render_template('"foo_bundle", "file2", "file3"')
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 129, in render_template
return Template('{% load assets %}{% assets '+args+' %}{{ ASSET_URL }};{% endassets %}').render(Context(ctx))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
ERROR: Using commas is optional.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 158, in test_with_no_commas
self.render_template('"file1" "file2" "file3"')
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 129, in render_template
return Template('{% load assets %}{% assets '+args+' %}{{ ASSET_URL }};{% endassets %}').render(Context(ctx))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
ERROR: tests.test_django.TestTemplateTag.test_with_vars
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 144, in test_with_vars
self.render_template('var1 var2', {'var1': self.foo_bundle, 'var2': 'a_file'})
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 129, in render_template
return Template('{% load assets %}{% assets '+args+' %}{{ ASSET_URL }};{% endassets %}').render(Context(ctx))
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/base.py", line 184, in __init__
engine = Engine.get_default()
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/django/template/engine.py", line 81, in get_default
"No DjangoTemplates backend is configured.")
django.core.exceptions.ImproperlyConfigured: No DjangoTemplates backend is configured.
======================================================================
FAIL: tests.test_django.TestLoader.test
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 192, in test
assert len(bundles) == 1
AssertionError
======================================================================
FAIL: tests.test_django.TestLoader.test_cached_loader
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/adamj/Documents/Projects/django-assets/.tox/django110-py35/lib/python3.5/site-packages/nose/case.py", line 198, in runTest
self.test(*self.arg)
File "/Users/adamj/Documents/Projects/django-assets/tests/test_django.py", line 202, in test_cached_loader
assert len(bundles) == 1
AssertionError
----------------------------------------------------------------------
Ran 19 tests in 0.263s
I was trying to come up with a usage of manage.py assets watch
command.
What is the use case?
I wanted to use the fix for #12, but since no version of django-assets has been released in a while I had to install the git version, relying on webassets' git version as well (django-assets from git + webassets 0.9 doesn't work).
With these versions I end up with the following error:
Traceback:
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
118. response = middleware_method(request, e)
File "/Users/julen/dev/translate/pootle/pootle/middleware/errorpages.py" in process_exception
99. RequestContext(request))
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/loader.py" in render_to_string
169. return t.render(context_instance)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/base.py" in render
140. return self._render(context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/test/utils.py" in instrumented_test_render
85. return self.nodelist.render(context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/base.py" in render
840. bit = self.render_node(node, context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/debug.py" in render_node
78. return node.render(context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/loader_tags.py" in render
123. return compiled_parent._render(context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/test/utils.py" in instrumented_test_render
85. return self.nodelist.render(context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/base.py" in render
840. bit = self.render_node(node, context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/debug.py" in render_node
78. return node.render(context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/loader_tags.py" in render
62. result = block.nodelist.render(context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/base.py" in render
840. bit = self.render_node(node, context)
File "/Users/julen/.virtualenvs/pootle/lib/python2.7/site-packages/django/template/debug.py" in render_node
78. return node.render(context)
File "/Users/julen/.virtualenvs/pootle/src/django-assets/django_assets/templatetags/assets.py" in render
71. for url in bundle.urls(env=get_env()):
File "/Users/julen/.virtualenvs/pootle/src/webassets/src/webassets/bundle.py" in urls
781. ctx = wrap(self.env, self)
File "/Users/julen/.virtualenvs/pootle/src/webassets/src/webassets/bundle.py" in _get_env
368. raise BundleError('Bundle is not connected to an environment')
Exception Type: BundleError at /
Exception Value: Bundle is not connected to an environment
Haven't seen anything related in the existing issues or in the docs. If I go back to django-assets 0.8 everything works fine.
https://github.com/miracle2k/django-assets/blob/master/django_assets/__init__.py#L9 staters that the version must be 0.11 but the current version is 0.11.1 this causes py.test to fail with:
File "/home/vagrant/.virtualenvs/primarysite/bin/py.test", line 9, in
load_entry_point('pytest==2.7.2', 'console_scripts', 'py.test')()
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/config.py", line 32, in main
config = _prepareconfig(args, plugins)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/config.py", line 85, in _prepareconfig
pluginmanager=pluginmanager, args=args)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 521, in call
return self._docall(self.methods, kwargs)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 528, in _docall
firstresult=self.firstresult).execute()
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 393, in execute
return wrapped_call(method(_args), self.execute)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 109, in wrapped_call
wrap_controller.send(call_outcome)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/helpconfig.py", line 28, in pytest_cmdline_parse
config = outcome.get_result()
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 138, in get_result
py.builtin._reraise(_ex)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 123, in init
self.result = func()
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 394, in execute
res = method(*args)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/config.py", line 636, in pytest_cmdline_parse
self.parse(args)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/config.py", line 746, in parse
self._preparse(args)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/config.py", line 713, in _preparse
self.pluginmanager.consider_setuptools_entrypoints()
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/_pytest/core.py", line 278, in consider_setuptools_entrypoints
plugin = ep.load()
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/pkg_resources/init.py", line 2338, in load
self.require(_args, *_kwargs)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/pkg_resources/init.py", line 2355, in require
items = working_set.resolve(reqs, env, installer)
File "/home/vagrant/.virtualenvs/primarysite/local/lib/python2.7/site-packages/pkg_resources/init.py", line 832, in resolve
raise VersionConflict(dist, req).with_context(dependent_req)
pkg_resources.VersionConflict: (webassets 0.11.1 (/home/vagrant/.virtualenvs/primarysite/lib/python2.7/site-packages), Requirement.parse('webassets==0.11'))
DEBUG = True
, do not set ASSETS_DEBUG
manage.py collectstatic
{% assets "admin/js/vendor/jquery/jquery.js", output="jquery.js" %}{% endassets %}
BundleError
(file does not exist)ASSETS_DEBUG = True
Step 4. Everything works fine.
In other words, if ASSETS_DEBUG
is not set explicitly, django-assets should follow Django DEBUG
setting (and use staticfiles finders). Right now we are forced to change these settings simultaneously.
Django-assets is not thread safe. I've spent two days debugging this issue miracle2k/webassets#217 and it looks like cause is somewhere within get_env() function. With the following print statement added to django_assets/env.py I was not able to reproduce the problem anymore:
try:
imp.find_module('assets', app_path)
print "ASSETS FOUND:", app_path
except ImportError:
#if options.get('verbosity') > 1:
# print "no assets module"
continue
I use mod_wsgi daemon mode with multiple processes and threads and temporarily solved this issue by using threads=1. I think it needs to be fixed and until then there should be big red warning in the docs about thread safety. Now it exists only in source code (TODO):
def autoload():
"""Find assets by looking for an ``assets`` module within each
installed application, similar to how, e.g., the admin autodiscover
process works. This is were this code has been adapted from, too.
Only runs once.
TOOD: Not thread-safe!
TODO: Bring back to status output via callbacks?
"""
I am using django-assets on a multi-framework codebase where some tests won't require django.
What will happen is this:
______ ERROR at setup of test_allowed_to_peergrade[B-expired-False-NONE] _______
../../../virtualenv/python3.7.1/lib/python3.7/site-packages/django_assets/pytest_plugin.py:6: in set_django_assets_env
django_assets.env.get_env() # initialise django-assets settings
../../../virtualenv/python3.7.1/lib/python3.7/site-packages/django_assets/env.py:177: in get_env
env = DjangoEnvironment()
../../../virtualenv/python3.7.1/lib/python3.7/site-packages/webassets/env.py:724: in __init__
self.config.setdefault('debug', False)
../../../virtualenv/python3.7.1/lib/python3.7/site-packages/webassets/env.py:63: in setdefault
if not key in self:
../../../virtualenv/python3.7.1/lib/python3.7/site-packages/django_assets/env.py:51: in __contains__
return hasattr(settings, self._transform_key(key))
../../../virtualenv/python3.7.1/lib/python3.7/site-packages/django/conf/__init__.py:57: in __getattr__
self._setup(name)
../../../virtualenv/python3.7.1/lib/python3.7/site-packages/django/conf/__init__.py:42: in _setup
% (desc, ENVIRONMENT_VARIABLE))
E django.core.exceptions.ImproperlyConfigured: Requested setting ASSETS_DEBUG, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
In my case, django-assets is being pulled in with all pytest tests, since it's autouse=True
and attempting to access the settings singleton.
I'm thinking about what the best option would be to handle this - I think the best option would be to hold off autouse=True
and let the user add the fixture where and when they need it.
I run collectstatic
and then build assets
to compile and version my assets in production (webassets does the versioning). I use Whitenoise to serve production assets and (in theory) ensure far-future expire headers for fingerprinted assets.
However, Whitenoise doesn't think the compiled, versioned assets should have an far-futures expired header set because they aren't in the staticfiles.json manifest.
If I run collectstatic
again after build assets
it fingerprints the already fingerprinted files.
Is there a way we can solve this or work around it?
Key parts of my settings.py:
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
In assets.py:
from django_assets import Bundle, register
register('css', Bundle(
# list 3rd party and raw css here
'bower_components/fontawesome/css/font-awesome.css',
Bundle(
# list SCSS files here
'stylesheets/app.scss',
filters='pyscss',
output='css/styles.%(version)s.css'),
filters='cssrewrite',
output='css/app.%(version)s.css'))
it's awkward to leave django_assets enabled for unit testing
you need to set settings.DEBUG=True so that it finds files in the app static directories
which means I need to override settings in all the functional tests
Maybe it's worth considering having some "testing" mode in django_assets that enables ASSETS_DEBUG and debug behaviour if Django is running unit tests?
Note: I got this error when installing from pip. After I got done writing this I decided to install from github just to check. Turns out I don't get this error anymore (although now I'm trying to figure out how to get this working with S3/Cloudfront), but I figured I'd post this issue anyway just as a reminder to update pip, and for anyone else who may be running into this problem.
Everything works as expected when DEBUG = True
, but when switching to DEBUG = False
I get an error that looks like this:
KeyError: "Django settings doesn't define load_path
I've gotten this kind of error in the past and to solve I've had to add the setting (in this case, ASSETS_LOAD_PATH
) to my Django settings, but that isn't working for me. Unfortunately there seems to be no default set for this in settings.py, and additionally there seems to be no documentation for this setting, so I'm stuck guessing what it actually does. I have defined ASSETS_LOAD_PATH
in my Django settings to a variety of values and nothing changes. Here is the file I believe is causing the issues. I installed this from pip.
The current master contains some important fixes. It would be great to be able to reference a released version on our requirements.txt files instead of git commits.
Thanks.
When using django_assets with staticfiles, you are either required to run collectstatic
, or have ASSETS_DEBUG
set to True
.
Otherwise django_assets will not be able to find the files.
Please make this clear in the docs: right now it’s not mentioned there and you have to read the source code to understand why it’s not working as expected.
When I build assets %(version)s doesn't expand:
./manage.py assets build
Building bundle: css/common.min_%(version)s.css
2013-05-24 08:26:56,786 INFO Building bundle: css/common.min_%(version)s.css
Building bundle: js/editor.min_%(version)s.js
2013-05-24 08:26:56,794 INFO Building bundle: js/editor.min_%(version)s.js
Building bundle: js/admin.min_%(version)s.js
2013-05-24 08:26:56,799 INFO Building bundle: js/admin.min_%(version)s.js
Building bundle: css/editor.min_%(version)s.css
2013-05-24 08:26:56,800 INFO Building bundle: css/editor.min_%(version)s.css
Building bundle: js/common.min_%(version)s.js
2013-05-24 08:26:56,801 INFO Building bundle: js/common.min_%(version)s.js
Building bundle: css/custom/custom.min_%(version)s.css
2013-05-24 08:26:56,805 INFO Building bundle: css/custom/custom.min_%(version)s.css
Building bundle: css/admin.min_%(version)s.css
2013-05-24 08:26:56,805 INFO Building bundle: css/admin.min_%(version)s.css
Using Django_assets 0.8 version and Django 1.4.5: https://github.com/arky/pootle/blob/master/requirements/base.txt
Hi,
When running unittests (integration testing which render the templates) i receive teh following error:
...
File "/Users/mvantellingen/projects/autokopen.nl/autokopen/templates/layout.base.html", line 20, in block "head"
{%- assets "css_main" %}
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/webassets/ext/jinja2.py", line 181, in _render_assets
urls = bundle.urls(env=env)
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/webassets/bundle.py", line 681, in urls
urls.extend(bundle._urls(env, extra_filters, *args, **kwargs))
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/webassets/bundle.py", line 657, in _urls
url = env.resolver.resolve_source_to_url(cnt, org)
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/django_assets/env.py", line 152, in resolve_source_to_url
return Resolver.resolve_source_to_url(self, filepath, item)
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/webassets/env.py", line 300, in resolve_source_to_url
return self.query_url_mapping(filepath)
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/webassets/env.py", line 219, in query_url_mapping
mapping = self.env.url_mapping.items()
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/webassets/env.py", line 703, in _get_url_mapping
return self.config['url_mapping']
File "/Users/mvantellingen/virtualenvs/autokopen/lib/python2.7/site-packages/django_assets/env.py", line 65, in __getitem__
raise KeyError("Django settings doesn't define %s" % key)
KeyError: "Django settings doesn't define url_mapping"
TLDR - getting error: KeyError: "Django settings doesn't define RESOLVER"
Have this in my requirements.txt:
django-assets==0.10
webassets==0.10.1
Django 1.6.4
When running tests I get this error:
...
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/django_assets/templatetags/assets.py", line 72, in render
for url in bundle.urls():
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/webassets/bundle.py", line 786, in urls
for bundle, extra_filters, new_ctx in self.iterbuild(ctx):
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/webassets/bundle.py", line 682, in iterbuild
for bundle, _ in self.resolve_contents(ctx):
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/webassets/bundle.py", line 233, in resolve_contents
result = ctx.resolver.resolve_source(ctx, item)
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/webassets/bundle.py", line 50, in __getattr__
return self.getattr(self._parent, item)
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/webassets/bundle.py", line 58, in getattr
return getattr(object, item)
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/webassets/env.py", line 675, in _get_resolver
return self._storage['resolver']
File "/Users/jbb/.virtualenvs/fifteen5/lib/python2.7/site-packages/django_assets/env.py", line 62, in __getitem__
self._transform_key(key))
KeyError: "Django settings doesn't define RESOLVER"
In my test setup I use Django's override_settings
to configure a test environment like so:
DEBUG=True,
ASSETS_DEBUG=True,
ASSETS_AUTO_BUILD=True,
ASSETS_URL_EXPIRE=False,
ASSETS_UPDATER=None,
ASSETS_CACHE=False,
ASSETS_MANIFEST=False,
ASSETS_VERSIONS=False,
RemovedInDjango19Warning: django.utils.importlib will be removed in Django 1.9. -- and django-assets imports it.
When running ./manage.py assets build
you get the error ImportError: cannot import name LaxOptionParser
. This seems to have been removed:
If you run manage.py assets
with a command or options that aren't recognised, it prints an error but doesn't set a return code properly:
$ ./manage.py assets --invalid
usage: manage.py assets [-h] {watch,build,clean,check} ...
manage.py assets: error: too few arguments
$ echo $?
0
This makes it hard for scripts (like our deployment scripts) to detect that it failed with an error instead of succeeding.
I can see that django_assets.management.commands.assets.Command.handle()
expects commands to throw some kind of exception if they fail (that seems to be the only way to get a non-zero return code out of handle()):
def handle(self, *args, **options):
...
try:
impl.run_with_argv(args)
except AssetCommandError as e:
raise CommandError(e)
and that webassets.script.Command.run_with_argv()
swallows SystemExit
and returns 1
instead:
def run_with_argv(self, argv):
try:
ns = self.parser.parse_args(argv)
except SystemExit:
# We do not want the main() function to exit the program.
# See run() instead.
return 1
but I don't know which behaviour is correct. Should we catch a nonzero return code in handle
and throw an AssetCommandError
to propagate the exception out? Is it really wise to swallow and regenerate such exceptions?
IMHO, it's better not to throw SystemExit unless you mean it (thus, never in code that can be called by a library) and better not to hide and rethrow exceptions. Perhaps the django_assets Command should be using a lower-level interface to webassets
rather than calling its run_with_argv
method?
Django 1.7 allows creation of AppConfigs for project apps, using them to register application in INSTALLED_APPS.
'django_app.apps.AppConfig' instead of 'django_app'
Loading apps in django-assets assumes that apps are modules, what results in error:
ImportError: No module named 'django_app.apps.AppConfig'; 'django_app.apps' is not a package
Django documentation: https://docs.djangoproject.com/en/dev/ref/applications/
Doing
pip install git+https://github.com/miracle2k/django-assets.git#egg=django_assets
fails because of commit 9e7ab78
I'm trying to use whitenoise to serve my assets. To make the bundles I have to run
calls to {% static %} work fine and whitesnoise is used but for the {% assets %} call (DEBUG_ASSETS=False) the file is the wrong one.
Example code from my webpages:
<script type="text/javascript" src="/static/gen/packed.js?5df0a1aa"></script> <!-- generated using django-assets template tag -->
<script type='text/javascript' src='/static/js/contact_me.95b1c452b73b.js'></script> <!-- normal static call -->
Any insights?
I would be nice to have a new releases that has all the Django 1.8 compatibility changes.
As it relates to #3, #30 and other tickets, I've collected some thoughts on unit-testing.
The problem currently, as I understand it, is:
How should django-assets behave in tests? We may want to document this.
All that said, ASSETS_DEBUG does seem to be the better hook; it means I want to run from source, and that means it shouldn't require collectstatic to copy the source file to somewhere else first.
The name of the pytest plugin is currently "name_of_plugin", which isn't really what you'd expect.
I think "django_assets" would be a better name.
Also, please remove the print, since it'll print that for every test case.
Thanks!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.