agentsclimarketplace

Model entity validator

Skill smicolon/ai-kit/packs/django/skills/model-entity-validator

Convention packs for any AI coding tool - agents, skills, commands, and rules for 15 tools including Claude Code, Cursor, Windsurf, and Copilot

Install
npx -y skills add smicolon/ai-kit --skill model-entity-validator

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

This skill should be used when the user asks to "create a model", "add a Django model", "create database table", "add entity", "define schema", or when writing class definitions inheriting from models.Model. Validates BaseModel inheritance pattern.

SKILL.md

7.8 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it

Model/Entity Validator

Enforces Smicolon's BaseModel inheritance pattern for all Django models.

Activation Triggers

This skill activates when:

  • Creating new model files
  • Modifying existing models
  • Mentioning "model", "database", "schema", "table"
  • Writing class inheriting from models.Model
  • Running migrations
  • Discussing data structure

Core Principle: BaseModel Inheritance

NEVER repeat UUID/timestamp fields. All models inherit from BaseModel.

# ❌ WRONG - Repeating fields
class User(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_deleted = models.BooleanField(default=False)
    email = models.EmailField()

# ✅ CORRECT - Inherit from BaseModel
import core.models as _core_models

class User(_core_models.BaseModel):
    email = models.EmailField(unique=True)

Validation Process

Step 1: Check if BaseModel Exists

Before any action, check if the project has a BaseModel:

# Search for BaseModel in (in order):
# 1. core/models.py
# 2. shared/models.py
# 3. common/models.py
# 4. {app}/base.py

If BaseModel found: Suggest inheritance (Step 2a) If BaseModel NOT found: Create BaseModel first (Step 2b)

Step 2a: BaseModel Exists - Suggest Inheritance

When seeing:

class Product(models.Model):
    name = models.CharField(max_length=255)

Fix to:

import core.models as _core_models

class Product(_core_models.BaseModel):
    """Product model - inherits id, timestamps, soft delete from BaseModel."""

    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        db_table = 'products'

Step 2b: BaseModel NOT Found - Create It First

If no BaseModel exists, create it:

# core/models.py
import uuid
from django.db import models

class BaseModel(models.Model):
    """
    Abstract base model providing:
    - UUID primary key
    - Automatic timestamps (created_at, updated_at)
    - Soft delete support (is_deleted)

    All models MUST inherit from this class.
    """

    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_deleted = models.BooleanField(default=False)

    class Meta:
        abstract = True
        ordering = ['-created_at']

    def soft_delete(self) -> None:
        """Soft delete the record."""
        self.is_deleted = True
        self.save(update_fields=['is_deleted', 'updated_at'])

    def restore(self) -> None:
        """Restore a soft-deleted record."""
        self.is_deleted = False
        self.save(update_fields=['is_deleted', 'updated_at'])


class ActiveManager(models.Manager):
    """Manager that excludes soft-deleted records."""

    def get_queryset(self):
        return super().get_queryset().filter(is_deleted=False)

Report to developer:

BaseModel Created

Created core/models.py with BaseModel. All models should now inherit from it:

import core.models as _core_models

class YourModel(_core_models.BaseModel):
    # Your fields here - DO NOT add id, created_at, updated_at, is_deleted

Step 3: Detect Duplicate Fields

If seeing a model with explicit id/timestamp fields that inherits from BaseModel:

# ❌ WRONG - Duplicate fields
class User(_core_models.BaseModel):
    id = models.UUIDField(...)  # Already in BaseModel!
    created_at = models.DateTimeField(...)  # Already in BaseModel!
    email = models.EmailField()

Remove them:

# ✅ CORRECT - Only custom fields
class User(_core_models.BaseModel):
    email = models.EmailField(unique=True)

Step 4: Validate Indexes

Check if appropriate indexes exist:

class Product(_core_models.BaseModel):
    name = models.CharField(max_length=255)
    sku = models.CharField(max_length=100, unique=True)

    class Meta:
        db_table = 'products'
        indexes = [
            models.Index(fields=['sku']),  # Suggest for unique lookups
            models.Index(fields=['name']),  # Suggest for search
        ]

Complete Model Examples

Standard Model

# products/models.py
from django.db import models
import core.models as _core_models

class Product(_core_models.BaseModel):
    """Product model."""

    name = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    sku = models.CharField(max_length=100, unique=True, db_index=True)
    is_active = models.BooleanField(default=True)

    class Meta:
        db_table = 'products'
        verbose_name = 'Product'
        verbose_name_plural = 'Products'
        indexes = [
            models.Index(fields=['name']),
            models.Index(fields=['is_active', 'is_deleted']),
        ]

    def __str__(self):
        return self.name

User Model (with AbstractUser)

# users/models.py
import uuid
from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    """
    Custom User model with UUID and timestamps.

    Note: For User, override AbstractUser directly since it has its own
    ID handling. Add the standard fields manually.
    """

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_deleted = models.BooleanField(default=False)

    email = models.EmailField(unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        db_table = 'users'

Through Model (Many-to-Many)

# users/models.py
import core.models as _core_models

class UserOrganization(_core_models.BaseModel):
    """Through model for user-organization relationship."""

    user = models.ForeignKey('User', on_delete=models.CASCADE)
    organization = models.ForeignKey('Organization', on_delete=models.CASCADE)
    role = models.CharField(max_length=50)

    class Meta:
        db_table = 'user_organizations'
        unique_together = [['user', 'organization']]

Custom Managers

BaseModel provides soft delete. Add a custom manager for convenience:

import core.models as _core_models

class Product(_core_models.BaseModel):
    name = models.CharField(max_length=255)

    objects = models.Manager()  # All records
    active = _core_models.ActiveManager()  # Excludes soft-deleted

# Usage
Product.active.all()  # Only non-deleted
Product.objects.all()  # All including deleted

Validation Checklist

When reviewing a model, check:

  1. ✅ Inherits from BaseModel (or has explicit required fields for special cases)
  2. ✅ Does NOT duplicate fields from BaseModel
  3. ✅ Uses absolute import: import core.models as _core_models
  4. ✅ Has appropriate db_table name (singular or plural, snake_case)
  5. ✅ Has indexes on frequently queried fields
  6. ✅ Foreign keys have on_delete specified
  7. ✅ Has docstring explaining the model
  8. ✅ Has __str__ method for admin display

Behavior

Proactive enforcement:

  • Check if BaseModel exists FIRST
  • Suggest inheritance instead of field duplication
  • Remove duplicate fields automatically
  • Create BaseModel if missing
  • Explain WHY inheritance is better

Never:

  • Add duplicate id/timestamp fields to models
  • Let developers repeat base fields
  • Ignore existing BaseModel in the project

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,069. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.