Skip to main content
FootyCollect uses PostgreSQL as its primary database. The schema is designed to support multiple item types while maintaining data integrity, query performance, and extensibility.

Core Models

BaseItem

The foundation model for all collection items, containing common fields shared across all item types. Table: collection_baseitem Key Fields:
Source: footycollect/collection/models.py:180-312 Item Type Choices:
  • jersey - Football jerseys/shirts
  • shorts - Match shorts
  • outerwear - Jackets, hoodies, windbreakers
  • tracksuit - Training tracksuits
  • pants - Training pants
  • other - Other memorabilia
Indexes:
Source: footycollect/collection/models.py:316-327

Jersey

Jersey-specific model using Multi-Table Inheritance. Table: collection_jersey
Source: footycollect/collection/models.py:379-402
The Jersey model uses the base_item field as its primary key, creating a one-to-one relationship with BaseItem. This is the core of the Multi-Table Inheritance pattern.

Shorts

Shorts-specific model. Table: collection_shorts
Source: footycollect/collection/models.py:508-523

Outerwear

Outerwear-specific model for jackets, hoodies, etc. Table: collection_outerwear
Source: footycollect/collection/models.py:535-556

Tracksuit

Tracksuit-specific model. Table: collection_tracksuit
Source: footycollect/collection/models.py:568-581

Supporting Models

Photo

Generic photo model that can attach to any item using Django’s GenericForeignKey. Table: collection_photo
Source: footycollect/collection/models.py:52-73
Photos support both original format (image) and optimized AVIF format (image_avif) for better performance. AVIF conversion happens asynchronously via Celery.

Color

Color model using hexadecimal values. Table: collection_color
Source: footycollect/collection/models.py:15-46

Size

Size information for items. Table: collection_size
Source: footycollect/collection/models.py:366-374

Core App Models

Club

Football club/team information. Table: core_club Fields:
  • name - Club name
  • slug - URL-friendly identifier (unique)
  • country - Country code
  • logo - Club logo URL
  • logo_dark - Dark mode logo URL
Indexes: slug, name

Season

Football season information. Table: core_season Fields:
  • year - Season year (format: “2023-24”)
  • first_year - First year of season (“2023”)
  • second_year - Second year of season (“2024”)
Indexes: year

Competition

Football competition/league information. Table: core_competition Fields:
  • name - Competition name
  • slug - URL-friendly identifier (unique)
  • logo - Competition logo URL
  • logo_dark - Dark mode logo URL
Indexes: slug

Brand

Kit manufacturer/brand information. Table: core_brand Fields:
  • name - Brand name
  • slug - URL-friendly identifier (unique)
  • logo - Brand logo URL
  • logo_dark - Dark mode logo URL
Indexes: slug

Entity Relationship Diagram

Query Patterns

Get All Items for User

Get Specific Item Type

Use select_related() for ForeignKey relationships and prefetch_related() for ManyToMany relationships to optimize queries and reduce database hits.

Get Public Items

Get Item with Specific Type Data

Custom Managers

FootyCollect provides custom managers for common query patterns:

BaseItemManager

Source: footycollect/collection/models.py:157-165

MTIManager

Source: footycollect/collection/models.py:169-177 Usage:

Data Integrity

Constraints

  • BaseItem.item_type must match the related model type
  • Cascade deletes: Deleting BaseItem automatically deletes related specific model (Jersey, Shorts, etc.)
  • Unique constraints on slugs for Club, Competition, Brand
  • Photo order validation ensures consistent ordering

Validation

Models implement save() methods to enforce data integrity:
Source: footycollect/collection/models.py:415-422

Indexes and Performance

Performance Indexes

BaseItem Queries:
  • (user_id, item_type) - User’s items by type
  • (user_id, is_private, is_draft) - Public/draft filtering
  • (user_id, created_at) - Chronological ordering
  • (club, season) - Club and season lookups
Photo Queries:
  • (content_type_id, object_id) - Generic foreign key lookups
  • order - Photo ordering
  • user_id - User’s photos
Lookup Tables:
  • slug indexes on Club, Competition, Brand for URL lookups
  • name indexes for text searches

Query Optimization Tips

Migration Strategy

Adding New Item Types

  1. Create new model with OneToOneField to BaseItem
  2. Add new item_type choice to BaseItem.ITEM_TYPE_CHOICES
  3. Implement save() method to set correct item_type
  4. Create migration: python manage.py makemigrations
  5. Apply migration: python manage.py migrate

Adding Fields

  • Common fields: Add to BaseItem
  • Type-specific fields: Add to specific model (Jersey, Shorts, etc.)
For more details on the Multi-Table Inheritance pattern, see Multi-Table Inheritance.