CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-rosetta

A Django application that facilitates the translation process of your Django projects

Pending
Overview
Eval results
Files

storage-backends.mddocs/

Storage Backends

Pluggable storage system for persisting translation work-in-progress data, supporting session-based, cache-based, or custom storage implementations. Storage backends handle temporary data during translation sessions, including unsaved changes, filters, and pagination state.

Capabilities

Base Storage Interface

Abstract base class defining the storage backend interface that all implementations must follow.

class BaseRosettaStorage:
    """
    Abstract base class for storage backends.
    
    Defines the interface that all Rosetta storage backends must implement
    for persisting translation session data.
    """
    
    def __init__(self, request):
        """
        Initialize storage backend with request context.
        
        Parameters:
        - request: Django HttpRequest instance
        """
    
    def set(self, key: str, value) -> None:
        """
        Store a value with the given key.
        
        Parameters:
        - key: Storage key string
        - value: Value to store (must be serializable)
        """
        raise NotImplementedError
    
    def get(self, key: str, default=None):
        """
        Retrieve a value by key.
        
        Parameters:
        - key: Storage key string
        - default: Default value if key not found
        
        Returns:
        Stored value or default
        """
        raise NotImplementedError
    
    def has(self, key: str) -> bool:
        """
        Check if key exists in storage.
        
        Parameters:
        - key: Storage key string
        
        Returns:
        Boolean indicating key existence
        """
        raise NotImplementedError
    
    def delete(self, key: str) -> None:
        """
        Delete a key from storage.
        
        Parameters:
        - key: Storage key string to delete
        """
        raise NotImplementedError

Session Storage Backend

Session-based storage implementation using Django's session framework.

class SessionRosettaStorage(BaseRosettaStorage):
    """
    Session-based storage backend.
    
    Stores translation data in Django sessions, persisting across
    browser sessions but limited to single user/browser. Good for
    development and single-user deployments.
    """
    
    def __init__(self, request):
        """Initialize with request session."""
        self.request = request
    
    def set(self, key: str, value) -> None:
        """Store value in session."""
    
    def get(self, key: str, default=None):
        """Retrieve value from session."""
    
    def has(self, key: str) -> bool:
        """Check if key exists in session."""
    
    def delete(self, key: str) -> None:
        """Delete key from session."""

Cache Storage Backend

Cache-based storage implementation using Django's caching framework (default).

class CacheRosettaStorage(BaseRosettaStorage):
    """
    Cache-based storage backend (default).
    
    Uses Django's caching framework for storage, supporting multiple
    cache backends (Redis, Memcached, database, etc.). Recommended
    for production deployments with multiple users.
    """
    
    def __init__(self, request):
        """Initialize with cache instance."""
        self.request = request
        self.cache = caches[rosetta_settings.CACHE_NAME]
    
    def set(self, key: str, value) -> None:
        """Store value in cache."""
    
    def get(self, key: str, default=None):
        """Retrieve value from cache."""
    
    def has(self, key: str) -> bool:
        """Check if key exists in cache."""
    
    def delete(self, key: str) -> None:
        """Delete key from cache."""

Dummy Storage Backend

No-operation storage implementation for testing or minimal setups.

class DummyRosettaStorage(BaseRosettaStorage):
    """
    No-operation storage backend.
    
    Provides storage interface but doesn't actually persist data.
    Useful for testing or environments where persistence isn't needed.
    """
    
    def set(self, key: str, value) -> None:
        """No-op set operation."""
        pass
    
    def get(self, key: str, default=None):
        """Always returns default value."""
        return default
    
    def has(self, key: str) -> bool:
        """Always returns False."""
        return False
    
    def delete(self, key: str) -> None:
        """No-op delete operation."""
        pass

Storage Factory

Factory function for creating storage backend instances.

def get_storage(request) -> BaseRosettaStorage:
    """
    Get configured storage instance for request.
    
    Creates and returns storage backend instance based on
    ROSETTA_STORAGE_CLASS setting.
    
    Parameters:
    - request: Django HttpRequest instance
    
    Returns:
    Storage backend instance implementing BaseRosettaStorage
    
    Raises:
    ImportError: If configured storage class cannot be imported
    """

# Cache instance for storage operations
cache = caches[rosetta_settings.CACHE_NAME]
"""Django cache instance used by cache storage backend."""

Configuration

Storage backends are configured through Django settings:

ROSETTA_STORAGE_CLASS: str = 'rosetta.storage.CacheRosettaStorage'
"""
Full Python path to storage backend class.
Available options:
- 'rosetta.storage.CacheRosettaStorage' (default, recommended)
- 'rosetta.storage.SessionRosettaStorage' 
- 'rosetta.storage.DummyRosettaStorage'
- Custom implementation path
"""

ROSETTA_CACHE_NAME: str = 'default'
"""
Name of Django cache backend to use with CacheRosettaStorage.
Must correspond to a cache defined in CACHES setting.
"""

Usage Examples

Basic Storage Configuration

# settings.py - Use default cache storage (recommended)
ROSETTA_STORAGE_CLASS = 'rosetta.storage.CacheRosettaStorage'
ROSETTA_CACHE_NAME = 'default'

# Ensure you have a cache configured
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
    }
}

Session Storage Configuration

# settings.py - Use session storage for development
ROSETTA_STORAGE_CLASS = 'rosetta.storage.SessionRosettaStorage'

# Ensure sessions are properly configured
MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    # ... other middleware
]

INSTALLED_APPS = [
    'django.contrib.sessions',
    # ... other apps
]

Custom Cache Backend

# settings.py - Use dedicated cache for Rosetta
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
    },
    'rosetta': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/2',
        'TIMEOUT': 3600,  # 1 hour timeout for translation sessions
    }
}

ROSETTA_STORAGE_CLASS = 'rosetta.storage.CacheRosettaStorage'
ROSETTA_CACHE_NAME = 'rosetta'

Custom Storage Backend Implementation

# myapp/storage.py - Custom storage backend
from rosetta.storage import BaseRosettaStorage
import json
import os

class FileRosettaStorage(BaseRosettaStorage):
    """File-based storage backend for Rosetta."""
    
    def __init__(self, request):
        self.request = request
        self.user_id = request.user.id if request.user.is_authenticated else 'anonymous'
        self.storage_dir = f'/tmp/rosetta_storage/{self.user_id}'
        os.makedirs(self.storage_dir, exist_ok=True)
    
    def _get_file_path(self, key):
        return os.path.join(self.storage_dir, f'{key}.json')
    
    def set(self, key, value):
        file_path = self._get_file_path(key)
        with open(file_path, 'w') as f:
            json.dump(value, f)
    
    def get(self, key, default=None):
        file_path = self._get_file_path(key)
        try:
            with open(file_path, 'r') as f:
                return json.load(f)
        except (FileNotFoundError, json.JSONDecodeError):
            return default
    
    def has(self, key):
        return os.path.exists(self._get_file_path(key))
    
    def delete(self, key):
        file_path = self._get_file_path(key)
        try:
            os.remove(file_path)
        except FileNotFoundError:
            pass

# settings.py
ROSETTA_STORAGE_CLASS = 'myapp.storage.FileRosettaStorage'

Programmatic Storage Usage

from rosetta.storage import get_storage

def my_view(request):
    """Example of programmatic storage usage."""
    
    # Get storage instance for request
    storage = get_storage(request)
    
    # Store translation session data
    storage.set('current_filter', {
        'language': 'fr',
        'status': 'untranslated'
    })
    
    # Retrieve stored data
    filter_data = storage.get('current_filter', {})
    
    # Check if key exists
    if storage.has('user_preferences'):
        preferences = storage.get('user_preferences')
    
    # Delete temporary data
    storage.delete('temp_data')
    
    return render(request, 'template.html')

Database Storage Backend

# myapp/storage.py - Database-backed storage
from rosetta.storage import BaseRosettaStorage
from django.core.cache import cache
from myapp.models import RosettaSessionData

class DatabaseRosettaStorage(BaseRosettaStorage):
    """Database-backed storage for persistent sessions."""
    
    def __init__(self, request):
        self.request = request
        self.user_id = request.user.id if request.user.is_authenticated else None
        self.session_key = request.session.session_key
    
    def _get_session_data(self):
        """Get or create session data object."""
        if self.user_id:
            obj, created = RosettaSessionData.objects.get_or_create(
                user_id=self.user_id,
                defaults={'data': {}}
            )
        else:
            obj, created = RosettaSessionData.objects.get_or_create(
                session_key=self.session_key,
                defaults={'data': {}}
            )
        return obj
    
    def set(self, key, value):
        obj = self._get_session_data()
        obj.data[key] = value
        obj.save()
    
    def get(self, key, default=None):
        obj = self._get_session_data()
        return obj.data.get(key, default)
    
    def has(self, key):
        obj = self._get_session_data()
        return key in obj.data
    
    def delete(self, key):
        obj = self._get_session_data()
        obj.data.pop(key, None)
        obj.save()

# myapp/models.py
from django.db import models
from django.contrib.auth.models import User

class RosettaSessionData(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    session_key = models.CharField(max_length=40, null=True, blank=True)
    data = models.JSONField(default=dict)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        unique_together = [['user'], ['session_key']]

Testing Storage Backends

# tests.py - Testing storage implementations
from django.test import TestCase, RequestFactory
from django.contrib.auth.models import User
from rosetta.storage import get_storage, CacheRosettaStorage, SessionRosettaStorage

class StorageBackendTests(TestCase):
    def setUp(self):
        self.factory = RequestFactory()
        self.user = User.objects.create_user('testuser', 'test@example.com', 'pass')
    
    def test_cache_storage(self):
        """Test cache storage backend."""
        request = self.factory.get('/')
        request.user = self.user
        
        storage = CacheRosettaStorage(request)
        
        # Test set/get
        storage.set('test_key', 'test_value')
        self.assertEqual(storage.get('test_key'), 'test_value')
        
        # Test has
        self.assertTrue(storage.has('test_key'))
        self.assertFalse(storage.has('nonexistent_key'))
        
        # Test delete
        storage.delete('test_key')
        self.assertFalse(storage.has('test_key'))
    
    def test_session_storage(self):
        """Test session storage backend."""
        request = self.factory.get('/')
        request.user = self.user
        request.session = {}
        
        storage = SessionRosettaStorage(request)
        
        # Test operations
        storage.set('session_key', {'data': 'value'})
        self.assertEqual(storage.get('session_key'), {'data': 'value'})
        
        # Test default value
        self.assertEqual(storage.get('missing_key', 'default'), 'default')

Install with Tessl CLI

npx tessl i tessl/pypi-django-rosetta

docs

access-control.md

configuration.md

django-signals.md

file-operations.md

index.md

storage-backends.md

template-integration.md

translation-services.md

web-interface.md

tile.json