From eab379a0284e2bf6faaf5d0238d6d96f6566055d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Hells=C3=A9n?= Date: Mon, 13 Oct 2025 04:15:24 +0200 Subject: [PATCH] Remove custom indexes from Twitch models Eliminates explicit index definitions and db_index usage from Django models and migrations, relying on default indexes and constraints. This simplifies model definitions and migration files, reducing maintenance overhead and potential redundancy. --- twitch/migrations/0001_initial.py | 211 ++++++++---------------------- twitch/models.py | 66 +--------- 2 files changed, 59 insertions(+), 218 deletions(-) diff --git a/twitch/migrations/0001_initial.py b/twitch/migrations/0001_initial.py index 47bf8c8..582fde2 100644 --- a/twitch/migrations/0001_initial.py +++ b/twitch/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2.7 on 2025-10-13 00:00 +# Generated by Django 5.2.7 on 2025-10-13 00:36 from __future__ import annotations import django.db.models.deletion @@ -17,30 +17,6 @@ class Migration(migrations.Migration): dependencies = [] operations = [ - migrations.CreateModel( - name="Game", - fields=[ - ("id", models.TextField(primary_key=True, serialize=False, verbose_name="Game ID")), - ( - "slug", - models.TextField( - blank=True, db_index=True, default="", help_text="Short unique identifier for the game.", max_length=200, verbose_name="Slug" - ), - ), - ("name", models.TextField(blank=True, db_index=True, default="", verbose_name="Name")), - ("display_name", models.TextField(blank=True, db_index=True, default="", verbose_name="Display name")), - ("box_art", models.URLField(blank=True, default="", max_length=500, verbose_name="Box art URL")), - ( - "box_art_file", - models.FileField(blank=True, help_text="Locally cached box art image served from this site.", null=True, upload_to="games/box_art/"), - ), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Timestamp when this game record was created.")), - ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this game record was last updated.")), - ], - options={ - "ordering": ["display_name"], - }, - ), migrations.CreateModel( name="Channel", fields=[ @@ -48,27 +24,20 @@ class Migration(migrations.Migration): "id", models.TextField(help_text="The unique Twitch identifier for the channel.", primary_key=True, serialize=False, verbose_name="Channel ID"), ), - ("name", models.TextField(db_index=True, help_text="The lowercase username of the channel.", verbose_name="Username")), - ( - "display_name", - models.TextField(db_index=True, help_text="The display name of the channel (with proper capitalization).", verbose_name="Display Name"), - ), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Timestamp when this channel record was created.")), + ("name", models.TextField(help_text="The lowercase username of the channel.", verbose_name="Username")), + ("display_name", models.TextField(help_text="The display name of the channel (with proper capitalization).", verbose_name="Display Name")), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Timestamp when this channel record was created.")), ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this channel record was last updated.")), ], options={ "ordering": ["display_name"], - "indexes": [ - models.Index(fields=["name"], name="twitch_chan_name_15d566_idx"), - models.Index(fields=["display_name"], name="twitch_chan_display_2bf213_idx"), - ], }, ), migrations.CreateModel( name="DropBenefit", fields=[ ("id", models.TextField(help_text="Unique Twitch identifier for the benefit.", primary_key=True, serialize=False)), - ("name", models.TextField(blank=True, db_index=True, default="N/A", help_text="Name of the drop benefit.")), + ("name", models.TextField(blank=True, default="N/A", help_text="Name of the drop benefit.")), ("image_asset_url", models.URLField(blank=True, default="", help_text="URL to the benefit's image asset.", max_length=500)), ( "image_file", @@ -76,27 +45,52 @@ class Migration(migrations.Migration): ), ( "created_at", - models.DateTimeField( - db_index=True, help_text="Timestamp when the benefit was created. This is from Twitch API and not auto-generated.", null=True - ), + models.DateTimeField(help_text="Timestamp when the benefit was created. This is from Twitch API and not auto-generated.", null=True), ), ("entitlement_limit", models.PositiveIntegerField(default=1, help_text="Maximum number of times this benefit can be earned.")), ("is_ios_available", models.BooleanField(default=False, help_text="Whether the benefit is available on iOS.")), - ( - "distribution_type", - models.TextField(blank=True, db_index=True, default="", help_text="Type of distribution for this benefit.", max_length=50), - ), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Timestamp when this benefit record was created.")), + ("distribution_type", models.TextField(blank=True, default="", help_text="Type of distribution for this benefit.", max_length=50)), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Timestamp when this benefit record was created.")), ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this benefit record was last updated.")), ], options={ "ordering": ["-created_at"], - "indexes": [ - models.Index(fields=["name"], name="twitch_drop_name_7125ff_idx"), - models.Index(fields=["created_at"], name="twitch_drop_created_a3563e_idx"), - models.Index(fields=["distribution_type"], name="twitch_drop_distrib_08b224_idx"), - models.Index(condition=models.Q(("is_ios_available", True)), fields=["is_ios_available"], name="benefit_ios_available_idx"), - ], + }, + ), + migrations.CreateModel( + name="Game", + fields=[ + ("id", models.TextField(primary_key=True, serialize=False, verbose_name="Game ID")), + ("slug", models.TextField(blank=True, default="", help_text="Short unique identifier for the game.", max_length=200, verbose_name="Slug")), + ("name", models.TextField(blank=True, default="", verbose_name="Name")), + ("display_name", models.TextField(blank=True, default="", verbose_name="Display name")), + ("box_art", models.URLField(blank=True, default="", max_length=500, verbose_name="Box art URL")), + ( + "box_art_file", + models.FileField(blank=True, help_text="Locally cached box art image served from this site.", null=True, upload_to="games/box_art/"), + ), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Timestamp when this game record was created.")), + ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this game record was last updated.")), + ], + options={ + "ordering": ["display_name"], + }, + ), + migrations.CreateModel( + name="Organization", + fields=[ + ( + "id", + models.TextField( + help_text="The unique Twitch identifier for the organization.", primary_key=True, serialize=False, verbose_name="Organization ID" + ), + ), + ("name", models.TextField(help_text="Display name of the organization.", unique=True, verbose_name="Name")), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Timestamp when this organization record was created.")), + ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this organization record was last updated.")), + ], + options={ + "ordering": ["name"], }, ), migrations.CreateModel( @@ -104,7 +98,7 @@ class Migration(migrations.Migration): fields=[ ("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), ("entitlement_limit", models.PositiveIntegerField(default=1, help_text="Max times this benefit can be claimed for this drop.")), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Timestamp when this drop-benefit edge was created.")), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Timestamp when this drop-benefit edge was created.")), ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this drop-benefit edge was last updated.")), ( "benefit", @@ -116,7 +110,7 @@ class Migration(migrations.Migration): name="DropCampaign", fields=[ ("id", models.TextField(help_text="Unique Twitch identifier for the campaign.", primary_key=True, serialize=False)), - ("name", models.TextField(db_index=True, help_text="Name of the drop campaign.")), + ("name", models.TextField(help_text="Name of the drop campaign.")), ("description", models.TextField(blank=True, help_text="Detailed description of the campaign.")), ("details_url", models.URLField(blank=True, default="", help_text="URL with campaign details.", max_length=500)), ("account_link_url", models.URLField(blank=True, default="", help_text="URL to link a Twitch account for the campaign.", max_length=500)), @@ -125,11 +119,11 @@ class Migration(migrations.Migration): "image_file", models.FileField(blank=True, help_text="Locally cached campaign image served from this site.", null=True, upload_to="campaigns/images/"), ), - ("start_at", models.DateTimeField(blank=True, db_index=True, help_text="Datetime when the campaign starts.", null=True)), - ("end_at", models.DateTimeField(blank=True, db_index=True, help_text="Datetime when the campaign ends.", null=True)), + ("start_at", models.DateTimeField(blank=True, help_text="Datetime when the campaign starts.", null=True)), + ("end_at", models.DateTimeField(blank=True, help_text="Datetime when the campaign ends.", null=True)), ("is_account_connected", models.BooleanField(default=False, help_text="Indicates if the user account is linked.")), ("allow_is_enabled", models.BooleanField(default=True, help_text="Whether the campaign allows participation.")), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Timestamp when this campaign record was created.")), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Timestamp when this campaign record was created.")), ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this campaign record was last updated.")), ( "allow_channels", @@ -155,24 +149,6 @@ class Migration(migrations.Migration): "ordering": ["-start_at"], }, ), - migrations.CreateModel( - name="Organization", - fields=[ - ( - "id", - models.TextField( - help_text="The unique Twitch identifier for the organization.", primary_key=True, serialize=False, verbose_name="Organization ID" - ), - ), - ("name", models.TextField(db_index=True, help_text="Display name of the organization.", unique=True, verbose_name="Name")), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Timestamp when this organization record was created.")), - ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this organization record was last updated.")), - ], - options={ - "ordering": ["name"], - "indexes": [models.Index(fields=["name"], name="twitch_orga_name_febe72_idx")], - }, - ), migrations.AddField( model_name="game", name="owner", @@ -190,15 +166,15 @@ class Migration(migrations.Migration): name="TimeBasedDrop", fields=[ ("id", models.TextField(help_text="Unique Twitch identifier for the time-based drop.", primary_key=True, serialize=False)), - ("name", models.TextField(db_index=True, help_text="Name of the time-based drop.")), + ("name", models.TextField(help_text="Name of the time-based drop.")), ( "required_minutes_watched", - models.PositiveIntegerField(blank=True, db_index=True, help_text="Minutes required to watch before earning this drop.", null=True), + models.PositiveIntegerField(blank=True, help_text="Minutes required to watch before earning this drop.", null=True), ), ("required_subs", models.PositiveIntegerField(default=0, help_text="Number of subscriptions required to unlock this drop.")), - ("start_at", models.DateTimeField(blank=True, db_index=True, help_text="Datetime when this drop becomes available.", null=True)), - ("end_at", models.DateTimeField(blank=True, db_index=True, help_text="Datetime when this drop expires.", null=True)), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Timestamp when this time-based drop record was created.")), + ("start_at", models.DateTimeField(blank=True, help_text="Datetime when this drop becomes available.", null=True)), + ("end_at", models.DateTimeField(blank=True, help_text="Datetime when this drop expires.", null=True)), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Timestamp when this time-based drop record was created.")), ("updated_at", models.DateTimeField(auto_now=True, help_text="Timestamp when this time-based drop record was last updated.")), ( "benefits", @@ -231,7 +207,7 @@ class Migration(migrations.Migration): name="TwitchGameData", fields=[ ("id", models.TextField(primary_key=True, serialize=False, verbose_name="Twitch Game ID")), - ("name", models.TextField(blank=True, db_index=True, default="", verbose_name="Name")), + ("name", models.TextField(blank=True, default="", verbose_name="Name")), ( "box_art_url", models.URLField( @@ -243,7 +219,7 @@ class Migration(migrations.Migration): ), ), ("igdb_id", models.TextField(blank=True, default="", verbose_name="IGDB ID")), - ("added_at", models.DateTimeField(auto_now_add=True, db_index=True, help_text="Record creation time.")), + ("added_at", models.DateTimeField(auto_now_add=True, help_text="Record creation time.")), ("updated_at", models.DateTimeField(auto_now=True, help_text="Record last update time.")), ( "game", @@ -262,83 +238,8 @@ class Migration(migrations.Migration): "ordering": ["name"], }, ), - migrations.AddIndex( - model_name="dropcampaign", - index=models.Index(fields=["name"], name="twitch_drop_name_3b70b3_idx"), - ), - migrations.AddIndex( - model_name="dropcampaign", - index=models.Index(fields=["start_at", "end_at"], name="twitch_drop_start_a_6e5fb6_idx"), - ), - migrations.AddIndex( - model_name="dropcampaign", - index=models.Index( - condition=models.Q(("end_at__isnull", False), ("start_at__isnull", False)), fields=["start_at", "end_at"], name="campaign_active_partial_idx" - ), - ), - migrations.AddConstraint( - model_name="dropcampaign", - constraint=models.CheckConstraint( - condition=models.Q(("start_at__isnull", True), ("end_at__isnull", True), ("end_at__gt", models.F("start_at")), _connector="OR"), - name="campaign_valid_date_range", - ), - ), - migrations.AddIndex( - model_name="game", - index=models.Index(fields=["display_name"], name="twitch_game_display_a35ba3_idx"), - ), - migrations.AddIndex( - model_name="game", - index=models.Index(fields=["name"], name="twitch_game_name_c92c15_idx"), - ), - migrations.AddIndex( - model_name="game", - index=models.Index(fields=["slug"], name="twitch_game_slug_a02d3c_idx"), - ), - migrations.AddIndex( - model_name="game", - index=models.Index(condition=models.Q(("owner__isnull", False)), fields=["owner"], name="game_owner_partial_idx"), - ), - migrations.AddIndex( - model_name="timebaseddrop", - index=models.Index(fields=["name"], name="twitch_time_name_47c0f4_idx"), - ), - migrations.AddIndex( - model_name="timebaseddrop", - index=models.Index(fields=["start_at", "end_at"], name="twitch_time_start_a_c481f1_idx"), - ), - migrations.AddIndex( - model_name="timebaseddrop", - index=models.Index(fields=["required_minutes_watched"], name="twitch_time_require_82c30c_idx"), - ), - migrations.AddIndex( - model_name="timebaseddrop", - index=models.Index(fields=["campaign", "start_at", "required_minutes_watched"], name="twitch_time_campaig_4cc3b7_idx"), - ), - migrations.AddConstraint( - model_name="timebaseddrop", - constraint=models.CheckConstraint( - condition=models.Q(("start_at__isnull", True), ("end_at__isnull", True), ("end_at__gt", models.F("start_at")), _connector="OR"), - name="drop_valid_date_range", - ), - ), - migrations.AddConstraint( - model_name="timebaseddrop", - constraint=models.CheckConstraint( - condition=models.Q(("required_minutes_watched__isnull", True), ("required_minutes_watched__gte", 0), _connector="OR"), - name="drop_positive_minutes", - ), - ), - migrations.AddIndex( - model_name="dropbenefitedge", - index=models.Index(fields=["drop", "benefit"], name="twitch_drop_drop_id_5a574c_idx"), - ), migrations.AddConstraint( model_name="dropbenefitedge", constraint=models.UniqueConstraint(fields=("drop", "benefit"), name="unique_drop_benefit"), ), - migrations.AddIndex( - model_name="twitchgamedata", - index=models.Index(fields=["name"], name="twitch_twit_name_5dda5f_idx"), - ), ] diff --git a/twitch/models.py b/twitch/models.py index dffa88c..fd39b95 100644 --- a/twitch/models.py +++ b/twitch/models.py @@ -1,7 +1,7 @@ from __future__ import annotations import logging -from typing import TYPE_CHECKING, ClassVar +from typing import TYPE_CHECKING from django.db import models from django.utils import timezone @@ -22,7 +22,6 @@ class Organization(models.Model): help_text="The unique Twitch identifier for the organization.", ) name = models.TextField( - db_index=True, unique=True, verbose_name="Name", help_text="Display name of the organization.", @@ -30,7 +29,6 @@ class Organization(models.Model): added_at = models.DateTimeField( auto_now_add=True, - db_index=True, help_text="Timestamp when this organization record was created.", ) updated_at = models.DateTimeField( @@ -40,9 +38,6 @@ class Organization(models.Model): class Meta: ordering = ["name"] - indexes: ClassVar[list] = [ - models.Index(fields=["name"]), - ] def __str__(self) -> str: """Return a string representation of the organization.""" @@ -58,20 +53,17 @@ class Game(models.Model): max_length=200, blank=True, default="", - db_index=True, verbose_name="Slug", help_text="Short unique identifier for the game.", ) name = models.TextField( blank=True, default="", - db_index=True, verbose_name="Name", ) display_name = models.TextField( blank=True, default="", - db_index=True, verbose_name="Display name", ) box_art = models.URLField( @@ -100,7 +92,6 @@ class Game(models.Model): added_at = models.DateTimeField( auto_now_add=True, - db_index=True, help_text="Timestamp when this game record was created.", ) updated_at = models.DateTimeField( @@ -110,12 +101,6 @@ class Game(models.Model): class Meta: ordering = ["display_name"] - indexes: ClassVar[list] = [ - models.Index(fields=["display_name"]), - models.Index(fields=["name"]), - models.Index(fields=["slug"]), - models.Index(fields=["owner"], condition=models.Q(owner__isnull=False), name="game_owner_partial_idx"), - ] def __str__(self) -> str: """Return a string representation of the game.""" @@ -177,7 +162,7 @@ class TwitchGameData(models.Model): help_text="Optional link to the local Game record for this Twitch game.", ) - name = models.TextField(blank=True, default="", db_index=True, verbose_name="Name") + name = models.TextField(blank=True, default="", verbose_name="Name") box_art_url = models.URLField( max_length=500, blank=True, @@ -187,14 +172,11 @@ class TwitchGameData(models.Model): ) igdb_id = models.TextField(blank=True, default="", verbose_name="IGDB ID") - added_at = models.DateTimeField(auto_now_add=True, db_index=True, help_text="Record creation time.") + added_at = models.DateTimeField(auto_now_add=True, help_text="Record creation time.") updated_at = models.DateTimeField(auto_now=True, help_text="Record last update time.") class Meta: ordering = ["name"] - indexes: ClassVar[list] = [ - models.Index(fields=["name"]), - ] def __str__(self) -> str: return self.name or self.id @@ -210,19 +192,16 @@ class Channel(models.Model): help_text="The unique Twitch identifier for the channel.", ) name = models.TextField( - db_index=True, verbose_name="Username", help_text="The lowercase username of the channel.", ) display_name = models.TextField( - db_index=True, verbose_name="Display Name", help_text="The display name of the channel (with proper capitalization).", ) added_at = models.DateTimeField( auto_now_add=True, - db_index=True, help_text="Timestamp when this channel record was created.", ) updated_at = models.DateTimeField( @@ -232,10 +211,6 @@ class Channel(models.Model): class Meta: ordering = ["display_name"] - indexes: ClassVar[list] = [ - models.Index(fields=["name"]), - models.Index(fields=["display_name"]), - ] def __str__(self) -> str: """Return a string representation of the channel.""" @@ -251,7 +226,6 @@ class DropCampaign(models.Model): help_text="Unique Twitch identifier for the campaign.", ) name = models.TextField( - db_index=True, help_text="Name of the drop campaign.", ) description = models.TextField( @@ -283,13 +257,11 @@ class DropCampaign(models.Model): help_text="Locally cached campaign image served from this site.", ) start_at = models.DateTimeField( - db_index=True, null=True, blank=True, help_text="Datetime when the campaign starts.", ) end_at = models.DateTimeField( - db_index=True, null=True, blank=True, help_text="Datetime when the campaign ends.", @@ -319,7 +291,6 @@ class DropCampaign(models.Model): added_at = models.DateTimeField( auto_now_add=True, - db_index=True, help_text="Timestamp when this campaign record was created.", ) updated_at = models.DateTimeField( @@ -330,12 +301,6 @@ class DropCampaign(models.Model): class Meta: ordering = ["-start_at"] - indexes: ClassVar[list] = [ - models.Index(fields=["name"]), - models.Index(fields=["start_at", "end_at"]), - models.Index(fields=["start_at", "end_at"], condition=models.Q(start_at__isnull=False, end_at__isnull=False), name="campaign_active_partial_idx"), - ] - def __str__(self) -> str: return self.name @@ -396,7 +361,6 @@ class DropBenefit(models.Model): help_text="Unique Twitch identifier for the benefit.", ) name = models.TextField( - db_index=True, blank=True, default="N/A", help_text="Name of the drop benefit.", @@ -415,7 +379,6 @@ class DropBenefit(models.Model): ) created_at = models.DateTimeField( null=True, - db_index=True, help_text="Timestamp when the benefit was created. This is from Twitch API and not auto-generated.", ) entitlement_limit = models.PositiveIntegerField( @@ -430,7 +393,6 @@ class DropBenefit(models.Model): ) distribution_type = models.TextField( max_length=50, - db_index=True, blank=True, default="", help_text="Type of distribution for this benefit.", @@ -438,7 +400,6 @@ class DropBenefit(models.Model): added_at = models.DateTimeField( auto_now_add=True, - db_index=True, help_text="Timestamp when this benefit record was created.", ) updated_at = models.DateTimeField( @@ -448,12 +409,6 @@ class DropBenefit(models.Model): class Meta: ordering = ["-created_at"] - indexes: ClassVar[list] = [ - models.Index(fields=["name"]), - models.Index(fields=["created_at"]), - models.Index(fields=["distribution_type"]), - models.Index(fields=["is_ios_available"], condition=models.Q(is_ios_available=True), name="benefit_ios_available_idx"), - ] def __str__(self) -> str: """Return a string representation of the drop benefit.""" @@ -469,11 +424,9 @@ class TimeBasedDrop(models.Model): help_text="Unique Twitch identifier for the time-based drop.", ) name = models.TextField( - db_index=True, help_text="Name of the time-based drop.", ) required_minutes_watched = models.PositiveIntegerField( - db_index=True, null=True, blank=True, help_text="Minutes required to watch before earning this drop.", @@ -483,13 +436,11 @@ class TimeBasedDrop(models.Model): help_text="Number of subscriptions required to unlock this drop.", ) start_at = models.DateTimeField( - db_index=True, null=True, blank=True, help_text="Datetime when this drop becomes available.", ) end_at = models.DateTimeField( - db_index=True, null=True, blank=True, help_text="Datetime when this drop expires.", @@ -511,7 +462,6 @@ class TimeBasedDrop(models.Model): added_at = models.DateTimeField( auto_now_add=True, - db_index=True, help_text="Timestamp when this time-based drop record was created.", ) updated_at = models.DateTimeField( @@ -521,12 +471,6 @@ class TimeBasedDrop(models.Model): class Meta: ordering = ["start_at"] - indexes: ClassVar[list] = [ - models.Index(fields=["name"]), - models.Index(fields=["start_at", "end_at"]), - models.Index(fields=["required_minutes_watched"]), - models.Index(fields=["campaign", "start_at", "required_minutes_watched"]), - ] def __str__(self) -> str: """Return a string representation of the time-based drop.""" @@ -554,7 +498,6 @@ class DropBenefitEdge(models.Model): added_at = models.DateTimeField( auto_now_add=True, - db_index=True, help_text="Timestamp when this drop-benefit edge was created.", ) updated_at = models.DateTimeField( @@ -566,9 +509,6 @@ class DropBenefitEdge(models.Model): constraints = [ models.UniqueConstraint(fields=("drop", "benefit"), name="unique_drop_benefit"), ] - indexes: ClassVar[list] = [ - models.Index(fields=["drop", "benefit"]), - ] def __str__(self) -> str: """Return a string representation of the drop benefit edge."""