tg-validation
Data validation patterns for the World of Darkness Django application including database constraints, model validators, and atomic transactions. Use when implementing XP/freebie spending transactions, adding database constraints to models, writing clean() validation methods, or ensuring data integrity for character stats.
$ 安裝
git clone https://github.com/charlesmsiegel/tg /tmp/tg && cp -r /tmp/tg/.claude/skills/tg-validation ~/.claude/skills/tg// tip: Run this command in your terminal to install the skill
SKILL.md
name: tg-validation description: Data validation patterns for the World of Darkness Django application including database constraints, model validators, and atomic transactions. Use when implementing XP/freebie spending transactions, adding database constraints to models, writing clean() validation methods, or ensuring data integrity for character stats.
Data Validation Patterns
This skill provides validation patterns for ensuring data integrity across the WoD application.
When to Use This Skill
- Adding
@transaction.atomicto multi-step operations (XP spending, freebie allocation) - Adding
CheckConstraintto model Meta classes - Writing
clean()methods for cross-field validation - Adding field validators (
MinValueValidator,MaxValueValidator) - Writing tests for validation logic
Quick Reference
Transaction Pattern (XP/Freebie Operations)
from django.db import transaction
from django.core.exceptions import ValidationError
class Character(Model):
@transaction.atomic
def spend_xp(self, trait_name, cost, category):
# Lock row for concurrent access
char = Character.objects.select_for_update().get(pk=self.pk)
if char.xp < cost:
raise ValidationError(f"Insufficient XP: need {cost}, have {char.xp}")
char.xp -= cost
char.spent_xp.append({...})
char.save(update_fields=['xp', 'spent_xp'])
Database Constraint Pattern
from django.db.models import CheckConstraint, Q
class Character(Model):
class Meta:
constraints = [
CheckConstraint(
check=Q(xp__gte=0),
name='%(app_label)s_%(class)s_xp_non_negative',
violation_error_message="XP cannot be negative"
),
]
Model Validation Pattern
class Human(Character):
def clean(self):
super().clean()
if self.temporary_willpower > self.willpower:
raise ValidationError({
'temporary_willpower': f"Cannot exceed permanent willpower ({self.willpower})"
})
Field Validator Pattern
from django.core.validators import MinValueValidator, MaxValueValidator
class AttributeBlock(models.Model):
strength = models.IntegerField(
default=1,
validators=[MinValueValidator(1), MaxValueValidator(10)]
)
Detailed Patterns
For detailed implementation patterns including:
- Full XP spending transaction implementation
- Scene XP award transactions
- All attribute/ability constraints
- Status state machine validation
- JSON schema validation for spent_xp
- Migration strategies for adding constraints
See references/validation-patterns.md
Priority Guidelines
| Priority | What to Validate | Pattern |
|---|---|---|
| CRITICAL | XP/freebie operations | @transaction.atomic + select_for_update() |
| HIGH | Numeric ranges (1-10, 0-5) | CheckConstraint + Field validators |
| MEDIUM | Cross-field rules | clean() method |
| LOW | JSON structure | JSON schema validation |
Testing Validation
from django.test import TestCase
from django.core.exceptions import ValidationError
from django.db import IntegrityError
class TestCharacterValidation(TestCase):
def test_xp_cannot_be_negative_db_constraint(self):
character.xp = -100
with self.assertRaises(IntegrityError):
character.save()
def test_xp_cannot_be_negative_model_validation(self):
character.xp = -100
with self.assertRaises(ValidationError):
character.full_clean()
Repository

charlesmsiegel
Author
charlesmsiegel/tg/.claude/skills/tg-validation
1
Stars
2
Forks
Updated4d ago
Added1w ago