Django integration for Python Dart Sass with django-compressor support
Project description
Django Dart Sass
Django integration for Python Dart Sass with django-compressor support and powerful Django-specific Sass functions.
Features
- 🚀 Fast Sass compilation using the Dart Sass compiler
- 🔧 Django integration with
static(),url-for(), andtheme-color()functions - 📦 django-compressor support for seamless asset pipeline integration
- 🎯 Two-tier function system - global decorators + contextual functions
- 📁 App-specific imports with
@import 'app:myapp/styles'syntax - ⚡ Production ready with comprehensive error handling and caching
- 🧪 100% test coverage with 77 passing tests
Installation
pip install django-dart-sass
For django-compressor integration:
pip install django-dart-sass[compressor]
Quick Start
1. Add to Django Settings
# settings.py
INSTALLED_APPS = [
# ... other apps
'django_dart_sass',
]
# Optional: Configure theme colors
SASS_THEME_COLORS = {
'primary': '#007bff',
'secondary': '#6c757d',
'success': '#28a745',
'danger': '#dc3545',
'warning': '#ffc107',
'info': '#17a2b8',
}
# Optional: Additional Sass load paths
SASS_LOAD_PATHS = [
BASE_DIR / 'assets' / 'sass',
BASE_DIR / 'components',
]
# Optional: Sass compilation options
SASS_DART_OPTIONS = {
'style': 'compressed',
'source_map': True,
}
2. Use Django Functions in Sass
// styles.scss
.header {
background-image: url(static('images/header-bg.jpg'));
color: theme-color('primary');
}
.api-link::after {
content: url-for('api:users');
}
3. Compile Sass
# In your views or management commands
from django_dart_sass import compile_string, compile_file
# Compile from string
result = compile_string("""
.test {
color: theme-color('primary');
background: url(static('images/bg.jpg'));
}
""")
print(result['css'])
# Compile from file
result = compile_file('path/to/styles.scss')
print(result['css'])
Django-Compressor Integration
Setup
# settings.py
COMPRESS_PRECOMPILERS = (
('text/x-scss', 'django_dart_sass.compressor.DartSassCompressor'),
)
COMPRESS_ENABLED = True
Template Usage
<!-- template.html -->
{% load compress %}
{% compress css %}
<link rel="stylesheet" type="text/x-scss" href="{% static 'styles/main.scss' %}" />
<style type="text/x-scss">
.dynamic-style {
color: theme-color('primary');
background: url(static('images/pattern.png'));
}
</style>
{% endcompress %}
Built-in Django Functions
static($path) - Static File URLs
Generate Django static file URLs:
// Input
.logo {
background-image: url(static('images/logo.png'));
}
// Output
.logo {
background-image: url('/static/images/logo.png');
}
url-for($name, ...) - URL Reversing
Reverse Django URLs with optional arguments:
// Input
.api-endpoint::after {
content: url-for('api:users');
}
.user-profile::after {
content: url-for('user:profile', 123);
}
// Output
.api-endpoint::after {
content: '/api/users/';
}
.user-profile::after {
content: '/users/123/';
}
theme-color($name) - Theme Colors
Access theme colors from Django settings:
// Input
.btn-primary {
background-color: theme-color('primary');
border-color: theme-color('primary');
}
// Output (with SASS_THEME_COLORS = {'primary': '#007bff'})
.btn-primary {
background-color: #007bff;
border-color: #007bff;
}
App-Specific Imports
Import Sass files from specific Django apps:
// Import from myapp/static/myapp/sass/variables.scss
@import 'app:myapp/variables';
// Import from myapp/static/myapp/components.scss
@import 'app:myapp/components';
// Standard imports still work
@import 'bootstrap/variables';
App Structure
myapp/
├── static/
│ └── myapp/
│ ├── sass/
│ │ ├── variables.scss
│ │ └── mixins.scss
│ └── components.scss
└── ...
Custom Functions
Global Functions (Decorator)
Register functions globally across all compilations:
# myapp/sass_functions.py
from django_dart_sass import sass_function
from dart_sass.value import SassString, SassNumber
@sass_function("asset-url($path)")
def asset_url(args):
"""Generate asset URLs with cache busting."""
path = args[0].assert_string().text
# Your custom logic here
versioned_path = f"{path}?v={get_asset_version(path)}"
return SassString(f'url("{versioned_path}")', quoted=False)
@sass_function("rem($pixels)")
def pixels_to_rem(args):
"""Convert pixels to rem units."""
pixels = args[0].assert_number().value
rem_value = pixels / 16 # Assuming 16px base
return SassNumber(rem_value, unit='rem')
Contextual Functions (Per-Compilation)
Override or add functions for specific compilations:
from django_dart_sass import compile_string
def custom_function(args):
return SassString("custom-value")
result = compile_string(scss_code, {
'functions': {
'custom($arg)': custom_function,
# This overrides any global function with same signature
}
})
Custom Importers
Global Importers (Decorator)
# myapp/sass_importers.py
from django_dart_sass import sass_importer
from dart_sass.importer import ImportResult
@sass_importer
def theme_importer(url, from_import):
"""Import theme files from a themes directory."""
if url.startswith('theme:'):
theme_name = url[6:] # Remove 'theme:' prefix
theme_path = f'themes/{theme_name}.scss'
try:
with open(theme_path, 'r') as f:
contents = f.read()
return ImportResult(contents=contents, syntax='scss')
except FileNotFoundError:
return None
return None # Let other importers handle this URL
Usage in Sass:
@import 'theme:dark';
@import 'theme:light';
Contextual Importers (Per-Compilation)
from django_dart_sass import compile_string
from django_dart_sass.importers import DjangoImporter
# Create custom importer for this compilation
custom_importer = DjangoImporter()
result = compile_string(scss_code, {
'importers': [custom_importer], # Higher priority than global importers
})
Advanced Configuration
Load Paths
Configure where Sass looks for imported files:
# settings.py
# Method 1: Django settings
SASS_LOAD_PATHS = [
BASE_DIR / 'assets' / 'sass',
BASE_DIR / 'node_modules',
'/usr/local/share/sass',
]
# Method 2: STATICFILES_DIRS (automatically included)
STATICFILES_DIRS = [
BASE_DIR / 'static',
BASE_DIR / 'assets',
]
# Method 3: Additional include paths
SASS_ADDITIONAL_INCLUDE_PATHS = [
'/custom/sass/path',
]
# Method 4: Embedded-specific paths
SASS_DART_INCLUDE_PATHS = [
'/embedded/sass/path',
]
Compilation Options
# settings.py
SASS_DART_OPTIONS = {
# Output style: 'expanded', 'compressed'
'style': 'compressed',
# Generate source maps
'source_map': True,
# Charset handling
'charset': True,
# Import paths (alternative to SASS_LOAD_PATHS)
'load_paths': ['/additional/path'],
# Quiet dependency warnings
'quiet_deps': True,
# Verbose output
'verbose': False,
}
Error Handling
The package provides comprehensive error handling:
from django_dart_sass import compile_string
from dart_sass.exception import CompileException
try:
result = compile_string("""
.invalid {
color: $undefined-variable;
}
""")
except CompileException as e:
print(f"Sass compilation error: {e}")
# Error includes line numbers and context
Performance Tips
- Use Global Functions: Register frequently-used functions globally with decorators
- Cache Compilation Results: The package handles internal caching, but consider Django's cache framework for compiled CSS
- Minimize Load Paths: Too many load paths can slow down import resolution
- Use Compressed Style: Set
'style': 'compressed'in production
Testing
The package includes comprehensive tests. Run them with:
# Install dev dependencies
pip install django-dart-sass[dev]
# Run tests
python -m pytest
# Run with coverage
python -m pytest --cov=django_dart_sass
Troubleshooting
Common Issues
ImportError: No module named 'compressor'
# Install django-compressor
pip install django-compressor
# Or install with compressor support
pip install django-dart-sass[compressor]
Sass compilation fails with "Can't find stylesheet to import"
- Check your
SASS_LOAD_PATHSsettings - Verify file paths and extensions (.scss vs .sass)
- Use app-specific imports:
@import 'app:myapp/file'
Functions not available in Sass
- Ensure
django_dart_sassis inINSTALLED_APPS - Check that function modules are imported (functions are registered on import)
- Verify function signatures match exactly
Debug Mode
Enable verbose logging:
# settings.py
LOGGING = {
'version': 1,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django_dart_sass': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Acknowledgments
This Django integration was developed by Harvey McQueen with assistance from Amazon Q Command-line. It builds upon:
- python-dart-sass - The core Python Dart Sass implementation
- Embedded Sass Protocol - The communication protocol
- Dart Sass - The Sass compilation engine
This is an independent Django integration and is not affiliated with or endorsed by the official Sass team or Django Software Foundation.
License
MIT License - see LICENSE file for details.
Related Projects
- django-compressor - Django asset compression framework
- django-sass-processor - Alternative Django Sass integration
- Dart Sass - The official Sass implementation
Changelog
0.1.0
- Initial release
- Two-tier function and importer system
- Django-compressor integration
- App-specific imports
- Built-in Django functions (static, url-for, theme-color)
- Comprehensive test suite
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_dart_sass-0.1.0.tar.gz.
File metadata
- Download URL: django_dart_sass-0.1.0.tar.gz
- Upload date:
- Size: 29.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5383e2108de3d4703acba58d0c224cd451b7d8916a4c08d085605e07aa3a74b9
|
|
| MD5 |
a62a7000f4bc6b2241682bcca03d2d22
|
|
| BLAKE2b-256 |
c913f5ea4a271d043b0b86ab12f7b45485d9a1398ff373d26f16f2e116eeaaaa
|
Provenance
The following attestation bundles were made for django_dart_sass-0.1.0.tar.gz:
Publisher:
publish.yml on hmcqueen/django-dart-sass
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_dart_sass-0.1.0.tar.gz -
Subject digest:
5383e2108de3d4703acba58d0c224cd451b7d8916a4c08d085605e07aa3a74b9 - Sigstore transparency entry: 540313827
- Sigstore integration time:
-
Permalink:
hmcqueen/django-dart-sass@22364d6b1f57313ac0ac6896b6026f62fbcb1f3b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/hmcqueen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@22364d6b1f57313ac0ac6896b6026f62fbcb1f3b -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_dart_sass-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_dart_sass-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0135931f21a29e037618169e0384ad274cada6d3414f49f7696c84d12ca62cb4
|
|
| MD5 |
81db2f22ddd7155187ac85a33bef97ca
|
|
| BLAKE2b-256 |
2b3a50cc0ade26a76004ec647601bf87d9932108efc9cc99a41eb72003ba3596
|
Provenance
The following attestation bundles were made for django_dart_sass-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on hmcqueen/django-dart-sass
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_dart_sass-0.1.0-py3-none-any.whl -
Subject digest:
0135931f21a29e037618169e0384ad274cada6d3414f49f7696c84d12ca62cb4 - Sigstore transparency entry: 540313829
- Sigstore integration time:
-
Permalink:
hmcqueen/django-dart-sass@22364d6b1f57313ac0ac6896b6026f62fbcb1f3b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/hmcqueen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@22364d6b1f57313ac0ac6896b6026f62fbcb1f3b -
Trigger Event:
push
-
Statement type: