django-sti-models


Namedjango-sti-models JSON
Version 0.1.14 PyPI version JSON
download
home_pageNone
SummaryImproved Django Single Table Inheritance (STI) models with admin integration and advanced utilities
upload_time2025-07-30 10:34:20
maintainerNone
docs_urlNone
authorKonrad Beck
requires_python<4.0.0,>=3.8.1
licenseNone
keywords django sti single-table-inheritance models polymorphic admin
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Django STI Models

An improved implementation of Single Table Inheritance (STI) for Django with better monkey patching, type safety, and performance.

## Features

- **Improved Monkey Patching**: Cleaner metaclass implementation that's more maintainable and less prone to conflicts
- **Type Safety**: Full type hints and validation throughout the codebase
- **Better Performance**: Optimized type registration and lookup mechanisms with caching
- **Enhanced Error Handling**: Comprehensive exception handling with meaningful error messages
- **Cleaner API**: More intuitive interface for working with typed models
- **Validation**: Built-in validation for type registration and field configuration
- **Django Admin Integration**: Seamless admin interface with type-aware filtering and forms
- **Management Commands**: Built-in commands for validation and maintenance
- **Advanced Utilities**: Comprehensive utility functions for common operations
- **Type Statistics**: Built-in support for analyzing type distribution

## Installation

```bash
# Using Poetry (recommended)
poetry add django-sti-models

# Using pip
pip install django-sti-models
```

**Requirements:**
- Django >= 4.2, < 6.0
- Python >= 3.8

## Quick Start

### 1. Define Your Base Model

```python
from django_sti_models import TypedModel, TypeField

class Animal(TypedModel):
    name = models.CharField(max_length=100)
    age = models.IntegerField()
    animal_type = TypeField()  # Use descriptive field names!
    
    class Meta:
        abstract = True
```

### 2. Create Your Subtypes

```python
class Dog(Animal):
    breed = models.CharField(max_length=50)
    
    def bark(self):
        return f"{self.name} says woof!"

class Cat(Animal):
    color = models.CharField(max_length=30)
    
    def meow(self):
        return f"{self.name} says meow!"

class Bird(Animal):
    wingspan = models.FloatField()
    
    def fly(self):
        return f"{self.name} is flying!"
```

### 3. Use Your Typed Models

```python
# Create instances
dog = Dog.objects.create(name="Rex", age=3, breed="Golden Retriever")
cat = Cat.objects.create(name="Whiskers", age=2, color="Orange")
bird = Bird.objects.create(name="Tweety", age=1, wingspan=12.5)

# Query by type
dogs = Dog.objects.all()  # Only returns Dog instances
cats = Cat.objects.all()  # Only returns Cat instances

# Query all animals
all_animals = Animal.objects.all()  # Returns all types

# Get the real instance type
animal = Animal.objects.first()
real_animal = animal.get_real_instance()  # Returns the correct subtype

# Check available types
available_types = Animal.get_all_types()
# Returns: {'Dog': <class 'Dog'>, 'Cat': <class 'Cat'>, 'Bird': <class 'Bird'>}
```

## Advanced Usage

### Custom Type Field Names

You can use a custom field name for the type field:

```python
class Vehicle(TypedModel):
    name = models.CharField(max_length=100)
    vehicle_kind = TypeField()  # Custom field name
    
    class Meta:
        abstract = True

class Car(Vehicle):
    doors = models.IntegerField()

class Motorcycle(Vehicle):
    engine_size = models.FloatField()
```

### Django Admin Integration

The package provides seamless Django admin integration:

```python
from django_sti_models import TypedModelAdmin, register_typed_models

# Option 1: Automatic registration
register_typed_models(Vehicle)

# Option 2: Custom admin class
class VehicleAdmin(TypedModelAdmin):
    list_display = ['name', 'vehicle_kind', 'created_at']
    list_filter = ['vehicle_kind']
    search_fields = ['name']

# Register with admin
admin.site.register(Vehicle, VehicleAdmin)
```

### Management Commands

Use built-in management commands for validation and maintenance:

```bash
# Validate all STI models
python manage.py validate_sti_models

# Validate specific app
python manage.py validate_sti_models --app myapp

# Show type statistics
python manage.py validate_sti_models --stats

# Validate specific model
python manage.py validate_sti_models --model Vehicle
```

### Advanced Utility Functions

```python
from django_sti_models.utils import (
    get_typed_queryset,
    create_typed_instance,
    get_type_hierarchy,
    get_type_statistics,
    filter_by_type,
    validate_type_consistency,
    migrate_type_field
)

# Get queryset filtered by specific types
land_vehicles = get_typed_queryset(Vehicle, ['Car', 'Motorcycle'])

# Create instance by type name
car = create_typed_instance(Vehicle, 'Car', name='Tesla', doors=4)

# Get type hierarchy
hierarchy = get_type_hierarchy(Vehicle)

# Get type statistics
stats = get_type_statistics(Vehicle)
# Returns: {'Car': 10, 'Motorcycle': 5}

# Filter existing queryset by type
cars_only = filter_by_type(Vehicle.objects.all(), 'Car')

# Validate type consistency
errors = validate_type_consistency(Vehicle)

# Migrate type field data
updated_count = migrate_type_field(Vehicle, 'old_type', 'new_type')
```

### Type Validation

The package includes comprehensive validation:

```python
from django_sti_models.utils import validate_type_registration

# Validate your type registration
errors = validate_type_registration(Vehicle)
if errors:
    print("Validation errors:", errors)
```

## Field Naming Best Practices

**✅ Good field names:**
- `animal_type` (for Animal models)
- `content_type` (for Content models)
- `vehicle_kind` (for Vehicle models)
- `user_role` (for User models)
- `product_category` (for Product models)

**❌ Avoid these:**
- `type` (Python reserved word)
- `kind` (too generic)
- `category` (too generic)

**Benefits of descriptive names:**
- Clearer code intent
- Better IDE support
- Avoids Python reserved word conflicts
- More maintainable code

## Improvements Over Original

### 1. Better Monkey Patching

The original django-typed-models used aggressive monkey patching that could conflict with other Django apps. This implementation:

- Uses a cleaner metaclass approach
- Minimizes interference with Django's internals
- Provides better error handling for conflicts
- Is more maintainable and debuggable

### 2. Enhanced Type Safety

- Full type hints throughout the codebase
- Better validation of type registration
- Improved error messages for debugging
- Type-safe manager implementations
- Generic type support

### 3. Performance Optimizations

- More efficient type registration
- Optimized queryset filtering
- Reduced memory usage
- Better caching of type information
- LRU caching for frequently accessed data

### 4. Cleaner API

- More intuitive method names
- Better separation of concerns
- Comprehensive utility functions
- Improved documentation
- Enhanced manager methods (get_or_create, update_or_create)

### 5. Django Admin Integration

- Seamless admin interface
- Type-aware filtering and forms
- Automatic type field handling
- Validation tools
- Statistics display

### 6. Management Commands

- Built-in validation commands
- Type consistency checking
- Statistics reporting
- Maintenance utilities

## Configuration

### Django Settings

Add to your `settings.py`:

```python
INSTALLED_APPS = [
    # ... other apps
    'django_sti_models',
]
```

### Type Field Configuration

The `TypeField` supports various configuration options:

```python
class MyModel(TypedModel):
    # Basic usage
    model_type = TypeField()
    
    # With custom configuration
    model_type = TypeField(
        max_length=50,
        db_index=True,
        editable=False
    )
```

### Admin Configuration

```python
# In your admin.py
from django_sti_models import TypedModelAdmin, register_typed_models

# For automatic registration
register_typed_models(YourBaseModel)

# For custom admin
class YourModelAdmin(TypedModelAdmin):
    list_display = ['name', 'model_type', 'created_at']
    list_filter = ['model_type']
    readonly_fields = ['model_type']
```

## Testing

```bash
# Run tests
poetry run pytest

# Run with coverage
poetry run pytest --cov=django_sti_models

# Run type checking
poetry run mypy django_sti_models/

# Run validation
python manage.py validate_sti_models
```

## Best Practices

### 1. Use Descriptive Type Field Names
```python
# Good
class Content(TypedModel):
    content_type = TypeField()

# Also good
class Vehicle(TypedModel):
    vehicle_kind = TypeField()
```

### 2. Implement Polymorphic Methods
```python
class Animal(TypedModel):
    def make_sound(self):
        raise NotImplementedError

class Dog(Animal):
    def make_sound(self):
        return "Woof!"

class Cat(Animal):
    def make_sound(self):
        return "Meow!"
```

### 3. Validate Type Consistency
```python
# Regular validation
from django_sti_models.utils import validate_type_consistency
errors = validate_type_consistency(Animal)

# Using management command
python manage.py validate_sti_models --app animals
```

### 4. Use Type-Aware Queries
```python
# Query specific types directly
dogs = Dog.objects.all()

# Use utility functions for complex filtering
land_animals = filter_by_type(Animal.objects.all(), ['Dog', 'Cat'])
```

### 5. Leverage Admin Integration
```python
# Automatic registration
register_typed_models(Animal)

# Custom admin with type-aware features
class AnimalAdmin(TypedModelAdmin):
    list_display = ['name', 'animal_type', 'age']
    list_filter = ['animal_type']
```

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Run the test suite
6. Submit a pull request

## License

MIT License - see LICENSE file for details.

## Acknowledgments

This project is inspired by and improves upon the original [django-typed-models](https://github.com/craigds/django-typed-models) by Craig de Stigter. 
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-sti-models",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0.0,>=3.8.1",
    "maintainer_email": null,
    "keywords": "django, sti, single-table-inheritance, models, polymorphic, admin",
    "author": "Konrad Beck",
    "author_email": "konrad.beck@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/53/fc/aec0d148c0b824652584ca71f9568ebb69cf083065ea9843f45f109074e2/django_sti_models-0.1.14.tar.gz",
    "platform": null,
    "description": "# Django STI Models\n\nAn improved implementation of Single Table Inheritance (STI) for Django with better monkey patching, type safety, and performance.\n\n## Features\n\n- **Improved Monkey Patching**: Cleaner metaclass implementation that's more maintainable and less prone to conflicts\n- **Type Safety**: Full type hints and validation throughout the codebase\n- **Better Performance**: Optimized type registration and lookup mechanisms with caching\n- **Enhanced Error Handling**: Comprehensive exception handling with meaningful error messages\n- **Cleaner API**: More intuitive interface for working with typed models\n- **Validation**: Built-in validation for type registration and field configuration\n- **Django Admin Integration**: Seamless admin interface with type-aware filtering and forms\n- **Management Commands**: Built-in commands for validation and maintenance\n- **Advanced Utilities**: Comprehensive utility functions for common operations\n- **Type Statistics**: Built-in support for analyzing type distribution\n\n## Installation\n\n```bash\n# Using Poetry (recommended)\npoetry add django-sti-models\n\n# Using pip\npip install django-sti-models\n```\n\n**Requirements:**\n- Django >= 4.2, < 6.0\n- Python >= 3.8\n\n## Quick Start\n\n### 1. Define Your Base Model\n\n```python\nfrom django_sti_models import TypedModel, TypeField\n\nclass Animal(TypedModel):\n    name = models.CharField(max_length=100)\n    age = models.IntegerField()\n    animal_type = TypeField()  # Use descriptive field names!\n    \n    class Meta:\n        abstract = True\n```\n\n### 2. Create Your Subtypes\n\n```python\nclass Dog(Animal):\n    breed = models.CharField(max_length=50)\n    \n    def bark(self):\n        return f\"{self.name} says woof!\"\n\nclass Cat(Animal):\n    color = models.CharField(max_length=30)\n    \n    def meow(self):\n        return f\"{self.name} says meow!\"\n\nclass Bird(Animal):\n    wingspan = models.FloatField()\n    \n    def fly(self):\n        return f\"{self.name} is flying!\"\n```\n\n### 3. Use Your Typed Models\n\n```python\n# Create instances\ndog = Dog.objects.create(name=\"Rex\", age=3, breed=\"Golden Retriever\")\ncat = Cat.objects.create(name=\"Whiskers\", age=2, color=\"Orange\")\nbird = Bird.objects.create(name=\"Tweety\", age=1, wingspan=12.5)\n\n# Query by type\ndogs = Dog.objects.all()  # Only returns Dog instances\ncats = Cat.objects.all()  # Only returns Cat instances\n\n# Query all animals\nall_animals = Animal.objects.all()  # Returns all types\n\n# Get the real instance type\nanimal = Animal.objects.first()\nreal_animal = animal.get_real_instance()  # Returns the correct subtype\n\n# Check available types\navailable_types = Animal.get_all_types()\n# Returns: {'Dog': <class 'Dog'>, 'Cat': <class 'Cat'>, 'Bird': <class 'Bird'>}\n```\n\n## Advanced Usage\n\n### Custom Type Field Names\n\nYou can use a custom field name for the type field:\n\n```python\nclass Vehicle(TypedModel):\n    name = models.CharField(max_length=100)\n    vehicle_kind = TypeField()  # Custom field name\n    \n    class Meta:\n        abstract = True\n\nclass Car(Vehicle):\n    doors = models.IntegerField()\n\nclass Motorcycle(Vehicle):\n    engine_size = models.FloatField()\n```\n\n### Django Admin Integration\n\nThe package provides seamless Django admin integration:\n\n```python\nfrom django_sti_models import TypedModelAdmin, register_typed_models\n\n# Option 1: Automatic registration\nregister_typed_models(Vehicle)\n\n# Option 2: Custom admin class\nclass VehicleAdmin(TypedModelAdmin):\n    list_display = ['name', 'vehicle_kind', 'created_at']\n    list_filter = ['vehicle_kind']\n    search_fields = ['name']\n\n# Register with admin\nadmin.site.register(Vehicle, VehicleAdmin)\n```\n\n### Management Commands\n\nUse built-in management commands for validation and maintenance:\n\n```bash\n# Validate all STI models\npython manage.py validate_sti_models\n\n# Validate specific app\npython manage.py validate_sti_models --app myapp\n\n# Show type statistics\npython manage.py validate_sti_models --stats\n\n# Validate specific model\npython manage.py validate_sti_models --model Vehicle\n```\n\n### Advanced Utility Functions\n\n```python\nfrom django_sti_models.utils import (\n    get_typed_queryset,\n    create_typed_instance,\n    get_type_hierarchy,\n    get_type_statistics,\n    filter_by_type,\n    validate_type_consistency,\n    migrate_type_field\n)\n\n# Get queryset filtered by specific types\nland_vehicles = get_typed_queryset(Vehicle, ['Car', 'Motorcycle'])\n\n# Create instance by type name\ncar = create_typed_instance(Vehicle, 'Car', name='Tesla', doors=4)\n\n# Get type hierarchy\nhierarchy = get_type_hierarchy(Vehicle)\n\n# Get type statistics\nstats = get_type_statistics(Vehicle)\n# Returns: {'Car': 10, 'Motorcycle': 5}\n\n# Filter existing queryset by type\ncars_only = filter_by_type(Vehicle.objects.all(), 'Car')\n\n# Validate type consistency\nerrors = validate_type_consistency(Vehicle)\n\n# Migrate type field data\nupdated_count = migrate_type_field(Vehicle, 'old_type', 'new_type')\n```\n\n### Type Validation\n\nThe package includes comprehensive validation:\n\n```python\nfrom django_sti_models.utils import validate_type_registration\n\n# Validate your type registration\nerrors = validate_type_registration(Vehicle)\nif errors:\n    print(\"Validation errors:\", errors)\n```\n\n## Field Naming Best Practices\n\n**\u2705 Good field names:**\n- `animal_type` (for Animal models)\n- `content_type` (for Content models)\n- `vehicle_kind` (for Vehicle models)\n- `user_role` (for User models)\n- `product_category` (for Product models)\n\n**\u274c Avoid these:**\n- `type` (Python reserved word)\n- `kind` (too generic)\n- `category` (too generic)\n\n**Benefits of descriptive names:**\n- Clearer code intent\n- Better IDE support\n- Avoids Python reserved word conflicts\n- More maintainable code\n\n## Improvements Over Original\n\n### 1. Better Monkey Patching\n\nThe original django-typed-models used aggressive monkey patching that could conflict with other Django apps. This implementation:\n\n- Uses a cleaner metaclass approach\n- Minimizes interference with Django's internals\n- Provides better error handling for conflicts\n- Is more maintainable and debuggable\n\n### 2. Enhanced Type Safety\n\n- Full type hints throughout the codebase\n- Better validation of type registration\n- Improved error messages for debugging\n- Type-safe manager implementations\n- Generic type support\n\n### 3. Performance Optimizations\n\n- More efficient type registration\n- Optimized queryset filtering\n- Reduced memory usage\n- Better caching of type information\n- LRU caching for frequently accessed data\n\n### 4. Cleaner API\n\n- More intuitive method names\n- Better separation of concerns\n- Comprehensive utility functions\n- Improved documentation\n- Enhanced manager methods (get_or_create, update_or_create)\n\n### 5. Django Admin Integration\n\n- Seamless admin interface\n- Type-aware filtering and forms\n- Automatic type field handling\n- Validation tools\n- Statistics display\n\n### 6. Management Commands\n\n- Built-in validation commands\n- Type consistency checking\n- Statistics reporting\n- Maintenance utilities\n\n## Configuration\n\n### Django Settings\n\nAdd to your `settings.py`:\n\n```python\nINSTALLED_APPS = [\n    # ... other apps\n    'django_sti_models',\n]\n```\n\n### Type Field Configuration\n\nThe `TypeField` supports various configuration options:\n\n```python\nclass MyModel(TypedModel):\n    # Basic usage\n    model_type = TypeField()\n    \n    # With custom configuration\n    model_type = TypeField(\n        max_length=50,\n        db_index=True,\n        editable=False\n    )\n```\n\n### Admin Configuration\n\n```python\n# In your admin.py\nfrom django_sti_models import TypedModelAdmin, register_typed_models\n\n# For automatic registration\nregister_typed_models(YourBaseModel)\n\n# For custom admin\nclass YourModelAdmin(TypedModelAdmin):\n    list_display = ['name', 'model_type', 'created_at']\n    list_filter = ['model_type']\n    readonly_fields = ['model_type']\n```\n\n## Testing\n\n```bash\n# Run tests\npoetry run pytest\n\n# Run with coverage\npoetry run pytest --cov=django_sti_models\n\n# Run type checking\npoetry run mypy django_sti_models/\n\n# Run validation\npython manage.py validate_sti_models\n```\n\n## Best Practices\n\n### 1. Use Descriptive Type Field Names\n```python\n# Good\nclass Content(TypedModel):\n    content_type = TypeField()\n\n# Also good\nclass Vehicle(TypedModel):\n    vehicle_kind = TypeField()\n```\n\n### 2. Implement Polymorphic Methods\n```python\nclass Animal(TypedModel):\n    def make_sound(self):\n        raise NotImplementedError\n\nclass Dog(Animal):\n    def make_sound(self):\n        return \"Woof!\"\n\nclass Cat(Animal):\n    def make_sound(self):\n        return \"Meow!\"\n```\n\n### 3. Validate Type Consistency\n```python\n# Regular validation\nfrom django_sti_models.utils import validate_type_consistency\nerrors = validate_type_consistency(Animal)\n\n# Using management command\npython manage.py validate_sti_models --app animals\n```\n\n### 4. Use Type-Aware Queries\n```python\n# Query specific types directly\ndogs = Dog.objects.all()\n\n# Use utility functions for complex filtering\nland_animals = filter_by_type(Animal.objects.all(), ['Dog', 'Cat'])\n```\n\n### 5. Leverage Admin Integration\n```python\n# Automatic registration\nregister_typed_models(Animal)\n\n# Custom admin with type-aware features\nclass AnimalAdmin(TypedModelAdmin):\n    list_display = ['name', 'animal_type', 'age']\n    list_filter = ['animal_type']\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests for new functionality\n5. Run the test suite\n6. Submit a pull request\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Acknowledgments\n\nThis project is inspired by and improves upon the original [django-typed-models](https://github.com/craigds/django-typed-models) by Craig de Stigter. ",
    "bugtrack_url": null,
    "license": null,
    "summary": "Improved Django Single Table Inheritance (STI) models with admin integration and advanced utilities",
    "version": "0.1.14",
    "project_urls": null,
    "split_keywords": [
        "django",
        " sti",
        " single-table-inheritance",
        " models",
        " polymorphic",
        " admin"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "21135de596a71246ada3ed0df2b003e544fc5a5b97ba372fe1deea21163ba5eb",
                "md5": "19384a47918d30f56d8ceacf0b39504d",
                "sha256": "a613bc676833abd824da7264cc39a65d7692020ebca3bc7d20ec790c7a4db064"
            },
            "downloads": -1,
            "filename": "django_sti_models-0.1.14-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "19384a47918d30f56d8ceacf0b39504d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0.0,>=3.8.1",
            "size": 19513,
            "upload_time": "2025-07-30T10:34:19",
            "upload_time_iso_8601": "2025-07-30T10:34:19.300108Z",
            "url": "https://files.pythonhosted.org/packages/21/13/5de596a71246ada3ed0df2b003e544fc5a5b97ba372fe1deea21163ba5eb/django_sti_models-0.1.14-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "53fcaec0d148c0b824652584ca71f9568ebb69cf083065ea9843f45f109074e2",
                "md5": "9ff7d7310c0785d5394214e80174a700",
                "sha256": "2b57d19d34814cf0d883c17ad4a080d9640491800d71b5c8920e3ad9bfd0fe79"
            },
            "downloads": -1,
            "filename": "django_sti_models-0.1.14.tar.gz",
            "has_sig": false,
            "md5_digest": "9ff7d7310c0785d5394214e80174a700",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0.0,>=3.8.1",
            "size": 17095,
            "upload_time": "2025-07-30T10:34:20",
            "upload_time_iso_8601": "2025-07-30T10:34:20.723641Z",
            "url": "https://files.pythonhosted.org/packages/53/fc/aec0d148c0b824652584ca71f9568ebb69cf083065ea9843f45f109074e2/django_sti_models-0.1.14.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-30 10:34:20",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "django-sti-models"
}
        
Elapsed time: 0.72836s