diff --git a/ram/bookshelf/migrations/0032_book_book_title_idx_catalog_catalog_mfr_idx_and_more.py b/ram/bookshelf/migrations/0032_book_book_title_idx_catalog_catalog_mfr_idx_and_more.py new file mode 100644 index 0000000..9fef8fb --- /dev/null +++ b/ram/bookshelf/migrations/0032_book_book_title_idx_catalog_catalog_mfr_idx_and_more.py @@ -0,0 +1,43 @@ +# Generated by Django 6.0.1 on 2026-01-18 13:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookshelf", "0031_alter_tocentry_authors_alter_tocentry_subtitle_and_more"), + ( + "metadata", + "0027_company_company_slug_idx_company_company_country_idx_and_more", + ), + ] + + operations = [ + migrations.AddIndex( + model_name="book", + index=models.Index(fields=["title"], name="book_title_idx"), + ), + migrations.AddIndex( + model_name="catalog", + index=models.Index(fields=["manufacturer"], name="catalog_mfr_idx"), + ), + migrations.AddIndex( + model_name="magazine", + index=models.Index(fields=["published"], name="magazine_published_idx"), + ), + migrations.AddIndex( + model_name="magazine", + index=models.Index(fields=["name"], name="magazine_name_idx"), + ), + migrations.AddIndex( + model_name="magazineissue", + index=models.Index(fields=["magazine"], name="mag_issue_mag_idx"), + ), + migrations.AddIndex( + model_name="magazineissue", + index=models.Index( + fields=["publication_month"], name="mag_issue_pub_month_idx" + ), + ), + ] diff --git a/ram/bookshelf/models.py b/ram/bookshelf/models.py index 2fd046b..ac9df3b 100644 --- a/ram/bookshelf/models.py +++ b/ram/bookshelf/models.py @@ -110,6 +110,12 @@ class Book(BaseBook): class Meta: ordering = ["title"] + indexes = [ + # Index for title searches (local field) + models.Index(fields=["title"], name="book_title_idx"), + # Note: published and publication_year are inherited from BaseBook/BaseModel + # and cannot be indexed here due to multi-table inheritance + ] def __str__(self): return self.title @@ -141,6 +147,14 @@ class Catalog(BaseBook): class Meta: ordering = ["manufacturer", "publication_year"] + indexes = [ + # Index for manufacturer filtering (local field) + models.Index( + fields=["manufacturer"], name="catalog_mfr_idx" + ), + # Note: published and publication_year are inherited from BaseBook/BaseModel + # and cannot be indexed here due to multi-table inheritance + ] def __str__(self): # if the object is new, return an empty string to avoid @@ -189,6 +203,12 @@ class Magazine(BaseModel): class Meta: ordering = [Lower("name")] + indexes = [ + # Index for published filtering + models.Index(fields=["published"], name="magazine_published_idx"), + # Index for name searches (case-insensitive via db_collation if needed) + models.Index(fields=["name"], name="magazine_name_idx"), + ] def __str__(self): return self.name @@ -229,6 +249,17 @@ class MagazineIssue(BaseBook): "publication_month", "issue_number", ] + indexes = [ + # Index for magazine filtering (local field) + models.Index(fields=["magazine"], name="mag_issue_mag_idx"), + # Index for publication month (local field) + models.Index( + fields=["publication_month"], + name="mag_issue_pub_month_idx", + ), + # Note: published and publication_year are inherited from BaseBook/BaseModel + # and cannot be indexed here due to multi-table inheritance + ] def __str__(self): return f"{self.magazine.name} - {self.issue_number}" diff --git a/ram/consist/migrations/0020_consist_consist_published_idx_and_more.py b/ram/consist/migrations/0020_consist_consist_published_idx_and_more.py new file mode 100644 index 0000000..21a2e63 --- /dev/null +++ b/ram/consist/migrations/0020_consist_consist_published_idx_and_more.py @@ -0,0 +1,50 @@ +# Generated by Django 6.0.1 on 2026-01-18 13:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("consist", "0019_consistitem_load"), + ( + "metadata", + "0027_company_company_slug_idx_company_company_country_idx_and_more", + ), + ("roster", "0041_rollingclass_roster_rc_company_idx_and_more"), + ] + + operations = [ + migrations.AddIndex( + model_name="consist", + index=models.Index(fields=["published"], name="consist_published_idx"), + ), + migrations.AddIndex( + model_name="consist", + index=models.Index(fields=["scale"], name="consist_scale_idx"), + ), + migrations.AddIndex( + model_name="consist", + index=models.Index(fields=["company"], name="consist_company_idx"), + ), + migrations.AddIndex( + model_name="consist", + index=models.Index( + fields=["published", "scale"], name="consist_pub_scale_idx" + ), + ), + migrations.AddIndex( + model_name="consistitem", + index=models.Index(fields=["load"], name="consist_item_load_idx"), + ), + migrations.AddIndex( + model_name="consistitem", + index=models.Index(fields=["order"], name="consist_item_order_idx"), + ), + migrations.AddIndex( + model_name="consistitem", + index=models.Index( + fields=["consist", "load"], name="consist_item_con_load_idx" + ), + ), + ] diff --git a/ram/consist/models.py b/ram/consist/models.py index bf5cf00..43c51b8 100644 --- a/ram/consist/models.py +++ b/ram/consist/models.py @@ -74,6 +74,18 @@ class Consist(BaseModel): class Meta: ordering = ["company", "-creation_time"] + indexes = [ + # Index for published filtering + models.Index(fields=["published"], name="consist_published_idx"), + # Index for scale filtering + models.Index(fields=["scale"], name="consist_scale_idx"), + # Index for company filtering + models.Index(fields=["company"], name="consist_company_idx"), + # Composite index for published+scale filtering + models.Index( + fields=["published", "scale"], name="consist_pub_scale_idx" + ), + ] class ConsistItem(models.Model): @@ -89,9 +101,19 @@ class ConsistItem(models.Model): constraints = [ models.UniqueConstraint( fields=["consist", "rolling_stock"], - name="one_stock_per_consist" + name="one_stock_per_consist", ) ] + indexes = [ + # Index for filtering by load status + models.Index(fields=["load"], name="consist_item_load_idx"), + # Index for ordering + models.Index(fields=["order"], name="consist_item_order_idx"), + # Composite index for consist+load filtering + models.Index( + fields=["consist", "load"], name="consist_item_con_load_idx" + ), + ] def __str__(self): return "{0}".format(self.rolling_stock) diff --git a/ram/metadata/migrations/0027_company_company_slug_idx_company_company_country_idx_and_more.py b/ram/metadata/migrations/0027_company_company_slug_idx_company_company_country_idx_and_more.py new file mode 100644 index 0000000..08671e2 --- /dev/null +++ b/ram/metadata/migrations/0027_company_company_slug_idx_company_company_country_idx_and_more.py @@ -0,0 +1,51 @@ +# Generated by Django 6.0.1 on 2026-01-18 13:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("metadata", "0026_alter_manufacturer_name_and_more"), + ] + + operations = [ + migrations.AddIndex( + model_name="company", + index=models.Index(fields=["slug"], name="company_slug_idx"), + ), + migrations.AddIndex( + model_name="company", + index=models.Index(fields=["country"], name="company_country_idx"), + ), + migrations.AddIndex( + model_name="company", + index=models.Index(fields=["freelance"], name="company_freelance_idx"), + ), + migrations.AddIndex( + model_name="manufacturer", + index=models.Index(fields=["category"], name="mfr_category_idx"), + ), + migrations.AddIndex( + model_name="manufacturer", + index=models.Index(fields=["slug"], name="mfr_slug_idx"), + ), + migrations.AddIndex( + model_name="manufacturer", + index=models.Index(fields=["category", "slug"], name="mfr_cat_slug_idx"), + ), + migrations.AddIndex( + model_name="scale", + index=models.Index(fields=["slug"], name="scale_slug_idx"), + ), + migrations.AddIndex( + model_name="scale", + index=models.Index(fields=["ratio_int"], name="scale_ratio_idx"), + ), + migrations.AddIndex( + model_name="scale", + index=models.Index( + fields=["-ratio_int", "-tracks"], name="scale_ratio_tracks_idx" + ), + ), + ] diff --git a/ram/metadata/models.py b/ram/metadata/models.py index 170b4ad..3894e13 100644 --- a/ram/metadata/models.py +++ b/ram/metadata/models.py @@ -48,10 +48,19 @@ class Manufacturer(SimpleBaseModel): ordering = ["category", "slug"] constraints = [ models.UniqueConstraint( - fields=["name", "category"], - name="unique_name_category" + fields=["name", "category"], name="unique_name_category" ) ] + indexes = [ + # Index for category filtering + models.Index(fields=["category"], name="mfr_category_idx"), + # Index for slug lookups + models.Index(fields=["slug"], name="mfr_slug_idx"), + # Composite index for category+slug (already in ordering) + models.Index( + fields=["category", "slug"], name="mfr_cat_slug_idx" + ), + ] def __str__(self): return self.name @@ -91,6 +100,14 @@ class Company(SimpleBaseModel): class Meta: verbose_name_plural = "Companies" ordering = ["slug"] + indexes = [ + # Index for slug lookups (used frequently in URLs) + models.Index(fields=["slug"], name="company_slug_idx"), + # Index for country filtering + models.Index(fields=["country"], name="company_country_idx"), + # Index for freelance filtering + models.Index(fields=["freelance"], name="company_freelance_idx"), + ] def __str__(self): return self.name @@ -165,6 +182,16 @@ class Scale(SimpleBaseModel): class Meta: ordering = ["-ratio_int", "-tracks", "scale"] + indexes = [ + # Index for slug lookups + models.Index(fields=["slug"], name="scale_slug_idx"), + # Index for ratio_int ordering and filtering + models.Index(fields=["ratio_int"], name="scale_ratio_idx"), + # Composite index for common ordering pattern + models.Index( + fields=["-ratio_int", "-tracks"], name="scale_ratio_tracks_idx" + ), + ] def get_absolute_url(self): return reverse( diff --git a/ram/roster/migrations/0041_rollingclass_roster_rc_company_idx_and_more.py b/ram/roster/migrations/0041_rollingclass_roster_rc_company_idx_and_more.py new file mode 100644 index 0000000..ae11c36 --- /dev/null +++ b/ram/roster/migrations/0041_rollingclass_roster_rc_company_idx_and_more.py @@ -0,0 +1,65 @@ +# Generated by Django 6.0.1 on 2026-01-18 13:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ( + "metadata", + "0027_company_company_slug_idx_company_company_country_idx_and_more", + ), + ("roster", "0040_alter_rollingstock_decoder_interface_order"), + ] + + operations = [ + migrations.AddIndex( + model_name="rollingclass", + index=models.Index(fields=["company"], name="roster_rc_company_idx"), + ), + migrations.AddIndex( + model_name="rollingclass", + index=models.Index(fields=["type"], name="roster_rc_type_idx"), + ), + migrations.AddIndex( + model_name="rollingclass", + index=models.Index( + fields=["company", "identifier"], name="roster_rc_co_ident_idx" + ), + ), + migrations.AddIndex( + model_name="rollingstock", + index=models.Index(fields=["published"], name="roster_published_idx"), + ), + migrations.AddIndex( + model_name="rollingstock", + index=models.Index(fields=["featured"], name="roster_featured_idx"), + ), + migrations.AddIndex( + model_name="rollingstock", + index=models.Index( + fields=["item_number_slug"], name="roster_item_slug_idx" + ), + ), + migrations.AddIndex( + model_name="rollingstock", + index=models.Index(fields=["road_number_int"], name="roster_road_num_idx"), + ), + migrations.AddIndex( + model_name="rollingstock", + index=models.Index( + fields=["published", "featured"], name="roster_pub_feat_idx" + ), + ), + migrations.AddIndex( + model_name="rollingstock", + index=models.Index( + fields=["manufacturer", "item_number_slug"], name="roster_mfr_item_idx" + ), + ), + migrations.AddIndex( + model_name="rollingstock", + index=models.Index(fields=["scale"], name="roster_scale_idx"), + ), + ] diff --git a/ram/roster/models.py b/ram/roster/models.py index a90eaed..ea632cb 100644 --- a/ram/roster/models.py +++ b/ram/roster/models.py @@ -38,6 +38,14 @@ class RollingClass(models.Model): ordering = ["company", "identifier"] verbose_name = "Class" verbose_name_plural = "Classes" + indexes = [ + models.Index(fields=["company"], name="roster_rc_company_idx"), + models.Index(fields=["type"], name="roster_rc_type_idx"), + models.Index( + fields=["company", "identifier"], + name="roster_rc_co_ident_idx", # Shortened to fit 30 char limit + ), + ] def __str__(self): return "{0} {1}".format(self.company, self.identifier) @@ -125,6 +133,30 @@ class RollingStock(BaseModel): class Meta: ordering = ["rolling_class", "road_number_int"] verbose_name_plural = "Rolling stock" + indexes = [ + # Index for published/featured filtering + models.Index(fields=["published"], name="roster_published_idx"), + models.Index(fields=["featured"], name="roster_featured_idx"), + # Index for item number searches + models.Index( + fields=["item_number_slug"], name="roster_item_slug_idx" + ), + # Index for road number searches and ordering + models.Index( + fields=["road_number_int"], name="roster_road_num_idx" + ), + # Composite index for common filtering patterns + models.Index( + fields=["published", "featured"], name="roster_pub_feat_idx" + ), + # Composite index for manufacturer+item_number lookups + models.Index( + fields=["manufacturer", "item_number_slug"], + name="roster_mfr_item_idx", + ), + # Index for scale filtering + models.Index(fields=["scale"], name="roster_scale_idx"), + ] def __str__(self): return "{0} {1}".format(self.rolling_class, self.road_number)