CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-extensions

Django Extensions is a comprehensive collection of custom extensions that enhance the Django web framework with additional management commands, utilities, and developer tools.

Pending
Overview
Eval results
Files

model-base-classes.mddocs/

Model Base Classes

Django Extensions provides abstract model classes that implement common functionality patterns including timestamps, activation status, and title/description/slug combinations. These base classes reduce boilerplate code and provide consistent implementations of frequently needed model patterns.

Capabilities

TimeStampedModel

Abstract base class that provides self-managed "created" and "modified" fields with automatic timestamp handling.

class TimeStampedModel(models.Model):
    created: CreationDateTimeField  # Automatically set on creation
    modified: ModificationDateTimeField  # Automatically updated on save
    
    def save(self, update_modified=True, **kwargs):
        """
        Save the model instance.
        
        Parameters:
        - update_modified: If False, prevents modification timestamp update
        """
    
    class Meta:
        get_latest_by = 'modified'
        abstract = True

Usage examples:

from django.db import models
from django_extensions.db.models import TimeStampedModel

class Article(TimeStampedModel):
    title = models.CharField(max_length=200)
    content = models.TextField()
    # created and modified fields are automatically added

class BlogPost(TimeStampedModel):
    title = models.CharField(max_length=200)
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    
    def save_without_timestamp_update(self, *args, **kwargs):
        # Save without updating the modified timestamp
        self.update_modified = False
        self.save(*args, **kwargs)

# Usage
article = Article.objects.create(title="My Article", content="Content")
print(article.created)  # DateTime when created
print(article.modified)  # Same as created initially

article.content = "Updated content"
article.save()
print(article.modified)  # Updated to current time

# Get latest article
latest = Article.objects.latest()  # Uses 'modified' field by default

TitleDescriptionModel

Abstract base class that provides standard title and description fields.

class TitleDescriptionModel(models.Model):
    title: CharField  # max_length=255
    description: TextField  # blank=True, null=True
    
    class Meta:
        abstract = True

Usage examples:

from django.db import models
from django_extensions.db.models import TitleDescriptionModel

class Category(TitleDescriptionModel):
    # Inherits title and description fields
    color = models.CharField(max_length=7)  # For hex color codes

class Product(TitleDescriptionModel):
    price = models.DecimalField(max_digits=10, decimal_places=2)
    sku = models.CharField(max_length=50, unique=True)

# Usage
category = Category.objects.create(
    title="Electronics",
    description="Electronic devices and accessories",
    color="#3498db"
)

TitleSlugDescriptionModel

Abstract base class that extends TitleDescriptionModel with an auto-generated slug field.

class TitleSlugDescriptionModel(TitleDescriptionModel):
    title: CharField  # Inherited from TitleDescriptionModel
    description: TextField  # Inherited from TitleDescriptionModel  
    slug: AutoSlugField  # Auto-populated from 'title'
    
    # Custom slugify function can be defined on the model
    def slugify_function(self, content):
        """
        Optional: Define custom slugification logic.
        
        Parameters:
        - content: The content to be slugified
        
        Returns:
        - str: The slugified content
        """
    
    class Meta:
        abstract = True

Usage examples:

from django.db import models
from django_extensions.db.models import TitleSlugDescriptionModel

class Page(TitleSlugDescriptionModel):
    content = models.TextField()
    is_published = models.BooleanField(default=False)

class CustomSlugPage(TitleSlugDescriptionModel):
    content = models.TextField()
    
    def slugify_function(self, content):
        # Custom slugification: use underscores instead of hyphens
        return content.replace(' ', '_').lower()

# Usage
page = Page.objects.create(
    title="About Us",
    description="Information about our company",
    content="We are a great company..."
)
print(page.slug)  # "about-us" (automatically generated)

# With custom slugify function
custom_page = CustomSlugPage.objects.create(
    title="Contact Info",
    content="Our contact information"
)
print(custom_page.slug)  # "contact_info" (uses custom function)

ActivatorModel System

A complete system for managing model activation status with querysets and managers.

class ActivatorQuerySet(models.QuerySet):
    def active(self):
        """Return queryset filtered to active instances only."""
        
    def inactive(self):
        """Return queryset filtered to inactive instances only."""

class ActivatorModelManager(models.Manager):
    def get_queryset(self):
        """Use ActivatorQuerySet for all queries."""
        
    def active(self):
        """Return active instances: Model.objects.active()"""
        
    def inactive(self):
        """Return inactive instances: Model.objects.inactive()"""

class ActivatorModel(models.Model):
    INACTIVE_STATUS: int = 0
    ACTIVE_STATUS: int = 1
    STATUS_CHOICES: tuple = (
        (INACTIVE_STATUS, 'Inactive'),
        (ACTIVE_STATUS, 'Active')
    )
    
    status: IntegerField  # choices=STATUS_CHOICES, default=ACTIVE_STATUS
    activate_date: DateTimeField  # blank=True, null=True
    deactivate_date: DateTimeField  # blank=True, null=True
    objects: ActivatorModelManager
    
    def save(self, *args, **kwargs):
        """Automatically set activate_date if not provided."""
    
    class Meta:
        ordering = ('status', '-activate_date')
        abstract = True

Usage examples:

from django.db import models
from django_extensions.db.models import ActivatorModel
from django.utils import timezone

class Campaign(ActivatorModel):
    name = models.CharField(max_length=200)
    budget = models.DecimalField(max_digits=10, decimal_places=2)

class Promotion(ActivatorModel):
    title = models.CharField(max_length=200)
    discount_percent = models.IntegerField()

# Usage - Creating instances
campaign = Campaign.objects.create(
    name="Summer Sale",
    budget=5000.00,
    # status defaults to ACTIVE_STATUS
    # activate_date is automatically set to now()
)

# Deactivating a campaign
campaign.status = Campaign.INACTIVE_STATUS
campaign.deactivate_date = timezone.now()
campaign.save()

# Querying active/inactive instances
active_campaigns = Campaign.objects.active()
inactive_campaigns = Campaign.objects.inactive()

# Using in templates or serializers
for campaign in Campaign.objects.active():
    print(f"Active: {campaign.name}")

# Scheduled activation
future_campaign = Campaign.objects.create(
    name="Holiday Sale",
    budget=10000.00,
    activate_date=timezone.now() + timezone.timedelta(days=30)
)

Combining Base Classes

Base classes can be combined to create models with multiple features:

from django.db import models
from django_extensions.db.models import TimeStampedModel, ActivatorModel

# Multiple inheritance
class ManagedContent(TimeStampedModel, ActivatorModel):
    title = models.CharField(max_length=200)
    content = models.TextField()
    
    class Meta:
        # Inherit ordering from ActivatorModel, add created
        ordering = ('status', '-activate_date', '-created')

# Custom combination with TitleSlugDescriptionModel
class PublishableArticle(TitleSlugDescriptionModel, TimeStampedModel, ActivatorModel):
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    featured_image = models.ImageField(upload_to='articles/', blank=True)
    
    def is_published(self):
        return self.status == self.ACTIVE_STATUS
    
    @classmethod 
    def published(cls):
        return cls.objects.active()

# Usage
article = PublishableArticle.objects.create(
    title="Django Best Practices",
    description="A guide to Django development",
    author=request.user
)
# Has: title, slug, description, created, modified, status, activate_date, deactivate_date

published_articles = PublishableArticle.published()

Model Patterns and Best Practices

# Pattern 1: Timestamped content with soft delete
class SoftDeleteTimeStampedModel(TimeStampedModel):
    is_deleted = models.BooleanField(default=False)
    deleted_at = models.DateTimeField(null=True, blank=True)
    
    def delete(self, using=None, keep_parents=False):
        # Soft delete instead of actual deletion
        self.is_deleted = True
        self.deleted_at = timezone.now()
        self.save()
    
    class Meta:
        abstract = True

# Pattern 2: Hierarchical categories with timestamps
class Category(TitleSlugDescriptionModel, TimeStampedModel):
    parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE)
    order = models.PositiveIntegerField(default=0)
    
    class Meta:
        ordering = ['order', 'title']
        verbose_name_plural = 'categories'

# Pattern 3: User-owned content with activation
class UserContent(TitleDescriptionModel, ActivatorModel, TimeStampedModel):
    owner = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    is_public = models.BooleanField(default=False)
    
    def can_view(self, user):
        if self.status != self.ACTIVE_STATUS:
            return False
        return self.is_public or self.owner == user or user.is_staff
    
    class Meta:
        abstract = True

Manager and QuerySet Customization

# Extending ActivatorModel with custom methods
class PublishedQuerySet(ActivatorQuerySet):
    def published(self):
        return self.active().filter(publish_date__lte=timezone.now())
    
    def featured(self):
        return self.published().filter(is_featured=True)

class PublishedManager(ActivatorModelManager):
    def get_queryset(self):
        return PublishedQuerySet(self.model, using=self._db)
    
    def published(self):
        return self.get_queryset().published()
    
    def featured(self):
        return self.get_queryset().featured()

class Article(TitleSlugDescriptionModel, ActivatorModel, TimeStampedModel):
    content = models.TextField()
    publish_date = models.DateTimeField(default=timezone.now)
    is_featured = models.BooleanField(default=False)
    
    objects = PublishedManager()
    
    class Meta:
        ordering = ['-publish_date']

# Usage
Article.objects.published()  # Active articles with publish_date <= now
Article.objects.featured()   # Published + featured articles

Install with Tessl CLI

npx tessl i tessl/pypi-django-extensions

docs

admin-extensions.md

index.md

management-commands.md

model-base-classes.md

model-fields.md

template-tags.md

validators.md

tile.json