Core - Usage Examples

Last Updated: 2026-07-09

Overview

Practical examples of using Core components. All imports use the nextango.apps.core package path.

Model Examples

Creating a Sanity-synced model

from django.db import models
from nextango.apps.core.models import SanityIntegratedModel

class MyDomainModel(SanityIntegratedModel):
    """UUID PK, timestamps, and Sanity sync come from the base class."""
    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)

    class Meta:
        ordering = ['-created_at']

Working with the sync lifecycle

instance.name = 'Updated Name'
instance.save()  # django_revision bumps; sync_status becomes 'out_of_sync'

if instance.needs_sync_to_sanity():
    push_to_sanity(instance)
    instance.mark_synced_to_sanity(sanity_rev='rev-abc123')

instance.get_sync_lag()  # 0 after a successful sync

Origin-aware deletion

# Django-owned model (_is_sanity_sot = False), deleted from internal code:
result = instance.safe_delete(origin='django_internal', hard_delete=True)

if result.action == 'blocked':
    for blocker in result.dependency_check.blockers:
        print(blocker.model, blocker.relation, blocker.count)
elif result.action == 'hard_deleted':
    print('gone:', result.reason)

Validator Examples

Sanitizing user input

from nextango.apps.core.validators import InputSanitizer

clean_text = InputSanitizer.sanitize_text(request.data['notes'], max_length=500)
clean_code = InputSanitizer.sanitize_identifier(request.data['store_code'])
clean_email = InputSanitizer.sanitize_email(request.data['email'])

Validating financial data

from django.core.exceptions import ValidationError
from nextango.apps.core.validators import FinancialValidator

try:
    amount = FinancialValidator.validate_payment_amount('149.99')
except ValidationError as e:
    return Response({'error': str(e)}, status=400)

Custom Field Example

EncryptedJSONField

from django.db import models
from nextango.apps.core.fields import EncryptedJSONField

class ProcessorConfig(models.Model):
    credentials = EncryptedJSONField()

config = ProcessorConfig()
config.credentials = {'api_key': 'secret', 'merchant_id': 'm_123'}
config.save()  # stored encrypted

config.refresh_from_db()
config.credentials['api_key']  # 'secret', decrypted transparently

Utility Examples

Caching a function result

from nextango.apps.core.utils.cache import cache_result

@cache_result(timeout=600, key_prefix='products', vary_on=['store_id'])
def get_products_for_display(store_id=None):
    return list(Product.objects.filter(is_active=True).values('id', 'name'))

Caching a ViewSet response with invalidation

from rest_framework_extensions.cache.decorators import cache_response
from nextango.apps.core.utils.cache import make_cache_key_func, invalidate_cache_pattern

class BrandViewSet(viewsets.ModelViewSet):
    @cache_response(timeout=3600, key_func=make_cache_key_func('brand'))
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

# In signals.py:
@receiver(post_save, sender=Brand)
def invalidate_brand_cache(sender, instance, **kwargs):
    invalidate_cache_pattern('brand:')

Performance logging

from nextango.apps.core.utils.performance import log_execution_time

@log_execution_time('ReportService.build_report')
def build_report(store_id):
    ...

Parsing analytics query params

from nextango.apps.core.utils.analytics import parse_date_range, parse_store_filter

def get(self, request):
    start_date, end_date = parse_date_range(request, default_days=30)
    store_q = parse_store_filter(request)
    qs = SaleTransaction.objects.filter(timestamp__date__range=(start_date, end_date))
    if store_q:
        qs = qs.filter(store_q)

Exception Handling Example

from nextango.apps.core.exceptions import handle_view_exception, BusinessLogicException

class MyViewSet(viewsets.ModelViewSet):
    @handle_view_exception
    def create(self, request, *args, **kwargs):
        if not request.data.get('store'):
            raise BusinessLogicException('Store is required', error_code='STORE_REQUIRED')
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # returns 400 with field detail
        ...

Was this page helpful?