Files
character-browser/models.py
Aodhan Collins c0e6cff7b7 Add outfit gallery and AI-powered creation for characters and outfits
- Add outfit gallery with CRUD operations (create, read, update, delete)
- Add AI-powered profile generation for both characters and outfits
- Add toggle to switch between AI generation and manual creation
- Auto-generate filenames from names with incrementing for duplicates
- Add 'full_body' and 'bottom' fields to wardrobe structure
- Update all character and outfit JSON files with new wardrobe fields
- Reorganize data into data/characters and data/clothing directories
- Update README with new features and JSON structure documentation
2026-02-19 18:34:46 +00:00

57 lines
2.3 KiB
Python

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Character(db.Model):
id = db.Column(db.Integer, primary_key=True)
character_id = db.Column(db.String(100), unique=True, nullable=False)
slug = db.Column(db.String(100), unique=True, nullable=False)
filename = db.Column(db.String(255), nullable=True)
name = db.Column(db.String(100), nullable=False)
data = db.Column(db.JSON, nullable=False)
default_fields = db.Column(db.JSON, nullable=True)
image_path = db.Column(db.String(255), nullable=True)
active_outfit = db.Column(db.String(100), default='default')
def get_active_wardrobe(self):
"""Get the currently active wardrobe outfit."""
wardrobe = self.data.get('wardrobe', {})
# Check if wardrobe is nested (new format) or flat (legacy)
if 'default' in wardrobe and isinstance(wardrobe.get('default'), dict):
# New nested format - return active outfit
return wardrobe.get(self.active_outfit or 'default', wardrobe.get('default', {}))
else:
# Legacy flat format - return as-is
return wardrobe
def get_available_outfits(self):
"""Get list of available outfit names."""
wardrobe = self.data.get('wardrobe', {})
if 'default' in wardrobe and isinstance(wardrobe.get('default'), dict):
return list(wardrobe.keys())
return ['default']
def __repr__(self):
return f'<Character {self.character_id}>'
class Outfit(db.Model):
id = db.Column(db.Integer, primary_key=True)
outfit_id = db.Column(db.String(100), unique=True, nullable=False)
slug = db.Column(db.String(100), unique=True, nullable=False)
filename = db.Column(db.String(255), nullable=True)
name = db.Column(db.String(100), nullable=False)
data = db.Column(db.JSON, nullable=False)
default_fields = db.Column(db.JSON, nullable=True)
image_path = db.Column(db.String(255), nullable=True)
def __repr__(self):
return f'<Outfit {self.outfit_id}>'
class Settings(db.Model):
id = db.Column(db.Integer, primary_key=True)
openrouter_api_key = db.Column(db.String(255), nullable=True)
openrouter_model = db.Column(db.String(100), default='google/gemini-2.0-flash-001')
def __repr__(self):
return '<Settings>'