Utilities¶
This documentation covers the utility subsystems that support TomSelect’s internal functionality: permission caching and logging.
Permission Caching¶
The permission caching system improves performance by caching user permission checks for autocomplete views. This is particularly useful in high-traffic applications where the same permission checks occur repeatedly.
Configuration¶
Permission caching is disabled by default. Enable it by setting a timeout in your Django settings:
# settings.py
TOMSELECT = {
"PERMISSION_CACHE": {
"TIMEOUT": 300, # Cache timeout in seconds (required to enable)
"KEY_PREFIX": "myapp", # Optional: prefix for cache keys
"NAMESPACE": "perms", # Optional: namespace for cache keys (default: "tomselect")
}
}
Behavior¶
DEBUG mode: Caching is automatically disabled when
DEBUG=TrueAnonymous users: Permissions are never cached for unauthenticated users
Auth overrides: Caching is skipped when
skip_authorization=Trueorallow_anonymous=True
Cache Backend Support¶
The system supports atomic operations for reliable cache invalidation:
Backend |
Atomic Operations |
Pattern Deletion |
|---|---|---|
Redis |
Yes |
Yes |
Memcached |
Yes |
No |
Local Memory |
Partial |
No |
Database |
No |
No |
For production deployments with permission changes, Redis or Memcached is recommended.
Invalidation¶
When user permissions change, invalidate the cache using the global permission_cache instance:
from django_tomselect.cache import permission_cache
# Invalidate all cached permissions for a specific user
permission_cache.invalidate_user(user_id=42)
# Invalidate all cached permissions globally
permission_cache.invalidate_all()
Using the Decorator¶
The @cache_permission decorator is used internally to cache permission check methods:
from django_tomselect.cache import cache_permission
class MyAutocompleteView(AutocompleteModelView):
model = MyModel
@cache_permission
def has_permission(self, request, action="view"):
# This result will be cached per user/model/action
return super().has_permission(request, action)
Logging¶
The logging system provides a controllable wrapper around Python’s standard logging module, with per-module loggers for fine-grained control.
Configuration¶
Logging is enabled by default. Disable it globally in your Django settings:
# settings.py
TOMSELECT = {
"ENABLE_LOGGING": False, # Disable all django-tomselect logging
}
Per-Module Logging¶
Each module in django-tomselect uses its own logger, following Python’s logging.getLogger(__name__) best practice. This allows you to configure different log levels for different parts of the package:
# settings.py
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
},
},
"loggers": {
# Configure all django-tomselect logging
"django_tomselect": {
"handlers": ["console"],
"level": "WARNING",
},
# Enable debug logging only for autocomplete views
"django_tomselect.autocompletes": {
"handlers": ["console"],
"level": "DEBUG",
},
# Quiet the widget rendering logs
"django_tomselect.widgets": {
"handlers": ["console"],
"level": "ERROR",
},
},
}
Available Module Loggers¶
Logger Name |
Description |
|---|---|
|
Autocomplete view processing, filtering, pagination |
|
Widget rendering, URL resolution, context building |
|
Form field initialization and validation |
|
Permission caching operations |
|
URL reversal, value escaping, sanitization |
|
Request storage in thread-local |
|
Lazy view and URL resolution |
|
Template tag rendering |
Runtime Control¶
You can control logging at runtime by getting a logger instance:
from django_tomselect.logging import get_logger
# Get a module-specific logger
logger = get_logger("django_tomselect.autocompletes")
# Check if logging is enabled
if logger.enabled:
print("Logging is active")
# Disable logging for this logger
logger.enabled = False
Temporarily Disabling Logging¶
Use the temporarily_disabled() decorator to suppress logging within a specific function:
from django_tomselect.logging import get_logger
logger = get_logger(__name__)
@logger.temporarily_disabled()
def my_function():
# All logging from this logger is suppressed here
do_something_noisy()
This is useful for tests or batch operations where logging output would be excessive.