Skip to main content

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(), and theme-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

  1. Use Global Functions: Register frequently-used functions globally with decorators
  2. Cache Compilation Results: The package handles internal caching, but consider Django's cache framework for compiled CSS
  3. Minimize Load Paths: Too many load paths can slow down import resolution
  4. 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_PATHS settings
  • Verify file paths and extensions (.scss vs .sass)
  • Use app-specific imports: @import 'app:myapp/file'

Functions not available in Sass

  • Ensure django_dart_sass is in INSTALLED_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

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

Acknowledgments

This Django integration was developed by Harvey McQueen with assistance from Amazon Q Command-line. It builds upon:

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

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_dart_sass-0.1.0.tar.gz (29.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_dart_sass-0.1.0-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

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

Hashes for django_dart_sass-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5383e2108de3d4703acba58d0c224cd451b7d8916a4c08d085605e07aa3a74b9
MD5 a62a7000f4bc6b2241682bcca03d2d22
BLAKE2b-256 c913f5ea4a271d043b0b86ab12f7b45485d9a1398ff373d26f16f2e116eeaaaa

See more details on using hashes here.

Provenance

The following attestation bundles were made for django_dart_sass-0.1.0.tar.gz:

Publisher: publish.yml on hmcqueen/django-dart-sass

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file django_dart_sass-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_dart_sass-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0135931f21a29e037618169e0384ad274cada6d3414f49f7696c84d12ca62cb4
MD5 81db2f22ddd7155187ac85a33bef97ca
BLAKE2b-256 2b3a50cc0ade26a76004ec647601bf87d9932108efc9cc99a41eb72003ba3596

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page