Make index view faster
This commit is contained in:
		
							
								
								
									
										1
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -17,6 +17,7 @@
 | 
				
			|||||||
    "sitewide",
 | 
					    "sitewide",
 | 
				
			||||||
    "socialaccount",
 | 
					    "socialaccount",
 | 
				
			||||||
    "Stresss",
 | 
					    "Stresss",
 | 
				
			||||||
 | 
					    "tocs",
 | 
				
			||||||
    "ttvdrops",
 | 
					    "ttvdrops",
 | 
				
			||||||
    "ulimits",
 | 
					    "ulimits",
 | 
				
			||||||
    "Valair",
 | 
					    "Valair",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,45 +1,31 @@
 | 
				
			|||||||
# Generated by Django 5.1 on 2024-08-12 03:47
 | 
					# Generated by Django 5.1 on 2024-08-12 23:16
 | 
				
			||||||
from __future__ import annotations
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import django.db.models.deletion
 | 
					import django.db.models.deletion
 | 
				
			||||||
import django.db.models.manager
 | 
					 | 
				
			||||||
from django.db import migrations, models
 | 
					from django.db import migrations, models
 | 
				
			||||||
 | 
					from django.db.migrations.operations.base import Operation
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					 | 
				
			||||||
    from django.db.migrations.operations.base import Operation
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Migration(migrations.Migration):
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					    replaces: list[tuple[str, str]] = [
 | 
				
			||||||
 | 
					        ("core", "0001_initial"),
 | 
				
			||||||
 | 
					        ("core", "0002_alter_benefit_time_based_drop_and_more"),
 | 
				
			||||||
 | 
					        ("core", "0003_alter_benefit_options_alter_channel_options_and_more"),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initial = True
 | 
					    initial = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dependencies: list[tuple[str, str]] = []
 | 
					    dependencies: list[tuple[str, str]] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    operations: list[Operation] = [
 | 
					    operations: list[Operation] = [
 | 
				
			||||||
        migrations.CreateModel(
 | 
					        migrations.CreateModel(
 | 
				
			||||||
            name="DropCampaign",
 | 
					            name="Owner",
 | 
				
			||||||
            fields=[
 | 
					            fields=[
 | 
				
			||||||
                ("created_at", models.DateTimeField(auto_created=True, null=True)),
 | 
					 | 
				
			||||||
                ("id", models.TextField(primary_key=True, serialize=False)),
 | 
					                ("id", models.TextField(primary_key=True, serialize=False)),
 | 
				
			||||||
                ("modified_at", models.DateTimeField(auto_now=True, null=True)),
 | 
					 | 
				
			||||||
                ("account_link_url", models.URLField(null=True)),
 | 
					 | 
				
			||||||
                ("description", models.TextField(null=True)),
 | 
					 | 
				
			||||||
                ("details_url", models.URLField(null=True)),
 | 
					 | 
				
			||||||
                ("ends_at", models.DateTimeField(null=True)),
 | 
					 | 
				
			||||||
                ("starts_at", models.DateTimeField(null=True)),
 | 
					 | 
				
			||||||
                ("image_url", models.URLField(null=True)),
 | 
					 | 
				
			||||||
                ("name", models.TextField(null=True)),
 | 
					                ("name", models.TextField(null=True)),
 | 
				
			||||||
                ("status", models.TextField(null=True)),
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            options={
 | 
					            options={
 | 
				
			||||||
                "abstract": False,
 | 
					                "abstract": False,
 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            managers=[
 | 
					 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.CreateModel(
 | 
					        migrations.CreateModel(
 | 
				
			||||||
            name="Game",
 | 
					            name="Game",
 | 
				
			||||||
@@ -49,70 +35,20 @@ class Migration(migrations.Migration):
 | 
				
			|||||||
                ("name", models.TextField(null=True)),
 | 
					                ("name", models.TextField(null=True)),
 | 
				
			||||||
                ("box_art_url", models.URLField(null=True)),
 | 
					                ("box_art_url", models.URLField(null=True)),
 | 
				
			||||||
                ("slug", models.TextField(null=True)),
 | 
					                ("slug", models.TextField(null=True)),
 | 
				
			||||||
            ],
 | 
					                (
 | 
				
			||||||
            options={
 | 
					                    "org",
 | 
				
			||||||
                "abstract": False,
 | 
					                    models.ForeignKey(
 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            managers=[
 | 
					 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.CreateModel(
 | 
					 | 
				
			||||||
            name="Owner",
 | 
					 | 
				
			||||||
            fields=[
 | 
					 | 
				
			||||||
                ("id", models.TextField(primary_key=True, serialize=False)),
 | 
					 | 
				
			||||||
                ("name", models.TextField(null=True)),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
            options={
 | 
					 | 
				
			||||||
                "abstract": False,
 | 
					 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            managers=[
 | 
					 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.CreateModel(
 | 
					 | 
				
			||||||
            name="Channel",
 | 
					 | 
				
			||||||
            fields=[
 | 
					 | 
				
			||||||
                ("twitch_id", models.TextField(primary_key=True, serialize=False)),
 | 
					 | 
				
			||||||
                ("display_name", models.TextField(null=True)),
 | 
					 | 
				
			||||||
                ("name", models.TextField(null=True)),
 | 
					 | 
				
			||||||
                ("twitch_url", models.URLField(null=True)),
 | 
					 | 
				
			||||||
                ("live", models.BooleanField(default=False)),
 | 
					 | 
				
			||||||
                ("drop_campaigns", models.ManyToManyField(related_name="channels", to="core.dropcampaign")),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
            options={
 | 
					 | 
				
			||||||
                "abstract": False,
 | 
					 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            managers=[
 | 
					 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.AddField(
 | 
					 | 
				
			||||||
            model_name="dropcampaign",
 | 
					 | 
				
			||||||
            name="game",
 | 
					 | 
				
			||||||
            field=models.ForeignKey(
 | 
					 | 
				
			||||||
                null=True,
 | 
					 | 
				
			||||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
					 | 
				
			||||||
                related_name="drop_campaigns",
 | 
					 | 
				
			||||||
                to="core.game",
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.AddField(
 | 
					 | 
				
			||||||
            model_name="game",
 | 
					 | 
				
			||||||
            name="org",
 | 
					 | 
				
			||||||
            field=models.ForeignKey(
 | 
					 | 
				
			||||||
                        null=True,
 | 
					                        null=True,
 | 
				
			||||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
					                        on_delete=django.db.models.deletion.CASCADE,
 | 
				
			||||||
                        related_name="games",
 | 
					                        related_name="games",
 | 
				
			||||||
                        to="core.owner",
 | 
					                        to="core.owner",
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            options={
 | 
				
			||||||
 | 
					                "abstract": False,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
        migrations.CreateModel(
 | 
					        migrations.CreateModel(
 | 
				
			||||||
            name="RewardCampaign",
 | 
					            name="RewardCampaign",
 | 
				
			||||||
            fields=[
 | 
					            fields=[
 | 
				
			||||||
@@ -145,41 +81,35 @@ class Migration(migrations.Migration):
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            options={
 | 
					            options={
 | 
				
			||||||
                "abstract": False,
 | 
					                "abstract": False,
 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            managers=[
 | 
					 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.CreateModel(
 | 
					        migrations.CreateModel(
 | 
				
			||||||
            name="Reward",
 | 
					            name="DropCampaign",
 | 
				
			||||||
            fields=[
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ("created_at", models.DateTimeField(auto_created=True, null=True)),
 | 
				
			||||||
                ("id", models.TextField(primary_key=True, serialize=False)),
 | 
					                ("id", models.TextField(primary_key=True, serialize=False)),
 | 
				
			||||||
 | 
					                ("modified_at", models.DateTimeField(auto_now=True, null=True)),
 | 
				
			||||||
 | 
					                ("account_link_url", models.URLField(null=True)),
 | 
				
			||||||
 | 
					                ("description", models.TextField(null=True)),
 | 
				
			||||||
 | 
					                ("details_url", models.URLField(null=True)),
 | 
				
			||||||
 | 
					                ("ends_at", models.DateTimeField(null=True)),
 | 
				
			||||||
 | 
					                ("starts_at", models.DateTimeField(null=True)),
 | 
				
			||||||
 | 
					                ("image_url", models.URLField(null=True)),
 | 
				
			||||||
                ("name", models.TextField(null=True)),
 | 
					                ("name", models.TextField(null=True)),
 | 
				
			||||||
                ("banner_image_url", models.URLField(null=True)),
 | 
					                ("status", models.TextField(null=True)),
 | 
				
			||||||
                ("thumbnail_image_url", models.URLField(null=True)),
 | 
					 | 
				
			||||||
                ("earnable_until", models.DateTimeField(null=True)),
 | 
					 | 
				
			||||||
                ("redemption_instructions", models.TextField(null=True)),
 | 
					 | 
				
			||||||
                ("redemption_url", models.URLField(null=True)),
 | 
					 | 
				
			||||||
                (
 | 
					                (
 | 
				
			||||||
                    "campaign",
 | 
					                    "game",
 | 
				
			||||||
                    models.ForeignKey(
 | 
					                    models.ForeignKey(
 | 
				
			||||||
                        null=True,
 | 
					                        null=True,
 | 
				
			||||||
                        on_delete=django.db.models.deletion.CASCADE,
 | 
					                        on_delete=django.db.models.deletion.CASCADE,
 | 
				
			||||||
                        related_name="rewards",
 | 
					                        related_name="drop_campaigns",
 | 
				
			||||||
                        to="core.rewardcampaign",
 | 
					                        to="core.game",
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            options={
 | 
					            options={
 | 
				
			||||||
                "abstract": False,
 | 
					                "abstract": False,
 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            managers=[
 | 
					 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.CreateModel(
 | 
					        migrations.CreateModel(
 | 
				
			||||||
            name="TimeBasedDrop",
 | 
					            name="TimeBasedDrop",
 | 
				
			||||||
@@ -204,12 +134,21 @@ class Migration(migrations.Migration):
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            options={
 | 
					            options={
 | 
				
			||||||
                "abstract": False,
 | 
					                "abstract": False,
 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            managers=[
 | 
					        ),
 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					        migrations.CreateModel(
 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					            name="Channel",
 | 
				
			||||||
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ("twitch_id", models.TextField(primary_key=True, serialize=False)),
 | 
				
			||||||
 | 
					                ("display_name", models.TextField(null=True)),
 | 
				
			||||||
 | 
					                ("name", models.TextField(null=True)),
 | 
				
			||||||
 | 
					                ("twitch_url", models.URLField(null=True)),
 | 
				
			||||||
 | 
					                ("live", models.BooleanField(default=False)),
 | 
				
			||||||
 | 
					                ("drop_campaigns", models.ManyToManyField(related_name="channels", to="core.dropcampaign")),
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
 | 
					            options={
 | 
				
			||||||
 | 
					                "abstract": False,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        migrations.CreateModel(
 | 
					        migrations.CreateModel(
 | 
				
			||||||
            name="Benefit",
 | 
					            name="Benefit",
 | 
				
			||||||
@@ -234,11 +173,30 @@ class Migration(migrations.Migration):
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            options={
 | 
					            options={
 | 
				
			||||||
                "abstract": False,
 | 
					                "abstract": False,
 | 
				
			||||||
                "base_manager_name": "prefetch_manager",
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            managers=[
 | 
					        ),
 | 
				
			||||||
                ("objects", django.db.models.manager.Manager()),
 | 
					        migrations.CreateModel(
 | 
				
			||||||
                ("prefetch_manager", django.db.models.manager.Manager()),
 | 
					            name="Reward",
 | 
				
			||||||
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ("id", models.TextField(primary_key=True, serialize=False)),
 | 
				
			||||||
 | 
					                ("name", models.TextField(null=True)),
 | 
				
			||||||
 | 
					                ("banner_image_url", models.URLField(null=True)),
 | 
				
			||||||
 | 
					                ("thumbnail_image_url", models.URLField(null=True)),
 | 
				
			||||||
 | 
					                ("earnable_until", models.DateTimeField(null=True)),
 | 
				
			||||||
 | 
					                ("redemption_instructions", models.TextField(null=True)),
 | 
				
			||||||
 | 
					                ("redemption_url", models.URLField(null=True)),
 | 
				
			||||||
 | 
					                (
 | 
				
			||||||
 | 
					                    "campaign",
 | 
				
			||||||
 | 
					                    models.ForeignKey(
 | 
				
			||||||
 | 
					                        null=True,
 | 
				
			||||||
 | 
					                        on_delete=django.db.models.deletion.CASCADE,
 | 
				
			||||||
 | 
					                        related_name="rewards",
 | 
				
			||||||
 | 
					                        to="core.rewardcampaign",
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
 | 
					            options={
 | 
				
			||||||
 | 
					                "abstract": False,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@@ -1,75 +0,0 @@
 | 
				
			|||||||
# Generated by Django 5.1 on 2024-08-12 22:19
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import auto_prefetch
 | 
					 | 
				
			||||||
import django.db.models.deletion
 | 
					 | 
				
			||||||
from django.db import migrations
 | 
					 | 
				
			||||||
from django.db.migrations.operations.base import Operation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Migration(migrations.Migration):
 | 
					 | 
				
			||||||
    dependencies: list[tuple[str, str]] = [
 | 
					 | 
				
			||||||
        ("core", "0001_initial"),
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    operations: list[Operation] = [
 | 
					 | 
				
			||||||
        migrations.AlterField(
 | 
					 | 
				
			||||||
            model_name="benefit",
 | 
					 | 
				
			||||||
            name="time_based_drop",
 | 
					 | 
				
			||||||
            field=auto_prefetch.ForeignKey(
 | 
					 | 
				
			||||||
                null=True,
 | 
					 | 
				
			||||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
					 | 
				
			||||||
                related_name="benefits",
 | 
					 | 
				
			||||||
                to="core.timebaseddrop",
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.AlterField(
 | 
					 | 
				
			||||||
            model_name="dropcampaign",
 | 
					 | 
				
			||||||
            name="game",
 | 
					 | 
				
			||||||
            field=auto_prefetch.ForeignKey(
 | 
					 | 
				
			||||||
                null=True,
 | 
					 | 
				
			||||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
					 | 
				
			||||||
                related_name="drop_campaigns",
 | 
					 | 
				
			||||||
                to="core.game",
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.AlterField(
 | 
					 | 
				
			||||||
            model_name="game",
 | 
					 | 
				
			||||||
            name="org",
 | 
					 | 
				
			||||||
            field=auto_prefetch.ForeignKey(
 | 
					 | 
				
			||||||
                null=True,
 | 
					 | 
				
			||||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
					 | 
				
			||||||
                related_name="games",
 | 
					 | 
				
			||||||
                to="core.owner",
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.AlterField(
 | 
					 | 
				
			||||||
            model_name="reward",
 | 
					 | 
				
			||||||
            name="campaign",
 | 
					 | 
				
			||||||
            field=auto_prefetch.ForeignKey(
 | 
					 | 
				
			||||||
                null=True,
 | 
					 | 
				
			||||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
					 | 
				
			||||||
                related_name="rewards",
 | 
					 | 
				
			||||||
                to="core.rewardcampaign",
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.AlterField(
 | 
					 | 
				
			||||||
            model_name="rewardcampaign",
 | 
					 | 
				
			||||||
            name="game",
 | 
					 | 
				
			||||||
            field=auto_prefetch.ForeignKey(
 | 
					 | 
				
			||||||
                null=True,
 | 
					 | 
				
			||||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
					 | 
				
			||||||
                related_name="reward_campaigns",
 | 
					 | 
				
			||||||
                to="core.game",
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
        migrations.AlterField(
 | 
					 | 
				
			||||||
            model_name="timebaseddrop",
 | 
					 | 
				
			||||||
            name="drop_campaign",
 | 
					 | 
				
			||||||
            field=auto_prefetch.ForeignKey(
 | 
					 | 
				
			||||||
                null=True,
 | 
					 | 
				
			||||||
                on_delete=django.db.models.deletion.CASCADE,
 | 
					 | 
				
			||||||
                related_name="drops",
 | 
					 | 
				
			||||||
                to="core.dropcampaign",
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ),
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
@@ -2,13 +2,12 @@ from __future__ import annotations
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import auto_prefetch
 | 
					 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
logger: logging.Logger = logging.getLogger(__name__)
 | 
					logger: logging.Logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Owner(auto_prefetch.Model):
 | 
					class Owner(models.Model):
 | 
				
			||||||
    """The company or person that owns the game.
 | 
					    """The company or person that owns the game.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Drops will be grouped by the owner. Users can also subscribe to owners.
 | 
					    Drops will be grouped by the owner. Users can also subscribe to owners.
 | 
				
			||||||
@@ -17,8 +16,11 @@ class Owner(auto_prefetch.Model):
 | 
				
			|||||||
    id = models.TextField(primary_key=True)  # "ad299ac0-f1a5-417d-881d-952c9aed00e9"
 | 
					    id = models.TextField(primary_key=True)  # "ad299ac0-f1a5-417d-881d-952c9aed00e9"
 | 
				
			||||||
    name = models.TextField(null=True)  # "Microsoft"
 | 
					    name = models.TextField(null=True)  # "Microsoft"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
 | 
					        return self.name or "Owner name unknown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Game(auto_prefetch.Model):
 | 
					
 | 
				
			||||||
 | 
					class Game(models.Model):
 | 
				
			||||||
    """This is the game we will see on the front end."""
 | 
					    """This is the game we will see on the front end."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    twitch_id = models.TextField(primary_key=True)  # "509658"
 | 
					    twitch_id = models.TextField(primary_key=True)  # "509658"
 | 
				
			||||||
@@ -27,13 +29,13 @@ class Game(auto_prefetch.Model):
 | 
				
			|||||||
    box_art_url = models.URLField(null=True)  # "https://static-cdn.jtvnw.net/ttv-boxart/Halo%20Infinite.jpg"
 | 
					    box_art_url = models.URLField(null=True)  # "https://static-cdn.jtvnw.net/ttv-boxart/Halo%20Infinite.jpg"
 | 
				
			||||||
    slug = models.TextField(null=True)  # "halo-infinite"
 | 
					    slug = models.TextField(null=True)  # "halo-infinite"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    org = auto_prefetch.ForeignKey(Owner, on_delete=models.CASCADE, related_name="games", null=True)
 | 
					    org = models.ForeignKey(Owner, on_delete=models.CASCADE, related_name="games", null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self) -> str:
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
        return self.name or "Game name unknown"
 | 
					        return self.name or "Game name unknown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DropCampaign(auto_prefetch.Model):
 | 
					class DropCampaign(models.Model):
 | 
				
			||||||
    """This is the drop campaign we will see on the front end."""
 | 
					    """This is the drop campaign we will see on the front end."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    id = models.TextField(primary_key=True)  # "f257ce6e-502a-11ef-816e-0a58a9feac02"
 | 
					    id = models.TextField(primary_key=True)  # "f257ce6e-502a-11ef-816e-0a58a9feac02"
 | 
				
			||||||
@@ -49,7 +51,7 @@ class DropCampaign(auto_prefetch.Model):
 | 
				
			|||||||
    ends_at = models.DateTimeField(null=True)  # "2024-08-12T05:59:59.999Z"
 | 
					    ends_at = models.DateTimeField(null=True)  # "2024-08-12T05:59:59.999Z"
 | 
				
			||||||
    starts_at = models.DateTimeField(null=True)  # "2024-08-11T11:00:00Z""
 | 
					    starts_at = models.DateTimeField(null=True)  # "2024-08-11T11:00:00Z""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    game = auto_prefetch.ForeignKey(Game, on_delete=models.CASCADE, related_name="drop_campaigns", null=True)
 | 
					    game = models.ForeignKey(Game, on_delete=models.CASCADE, related_name="drop_campaigns", null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # "https://static-cdn.jtvnw.net/twitch-quests-assets/CAMPAIGN/c8e02666-8b86-471f-bf38-7ece29a758e4.png"
 | 
					    # "https://static-cdn.jtvnw.net/twitch-quests-assets/CAMPAIGN/c8e02666-8b86-471f-bf38-7ece29a758e4.png"
 | 
				
			||||||
    image_url = models.URLField(null=True)
 | 
					    image_url = models.URLField(null=True)
 | 
				
			||||||
@@ -57,8 +59,11 @@ class DropCampaign(auto_prefetch.Model):
 | 
				
			|||||||
    name = models.TextField(null=True)  # "HCS Open Series - Week 1 - DAY 2 - AUG11"
 | 
					    name = models.TextField(null=True)  # "HCS Open Series - Week 1 - DAY 2 - AUG11"
 | 
				
			||||||
    status = models.TextField(null=True)  # "ACTIVE"
 | 
					    status = models.TextField(null=True)  # "ACTIVE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
 | 
					        return self.name or "Drop campaign name unknown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Channel(auto_prefetch.Model):
 | 
					
 | 
				
			||||||
 | 
					class Channel(models.Model):
 | 
				
			||||||
    """This is the channel we will see on the front end."""
 | 
					    """This is the channel we will see on the front end."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    twitch_id = models.TextField(primary_key=True)  # "222719079"
 | 
					    twitch_id = models.TextField(primary_key=True)  # "222719079"
 | 
				
			||||||
@@ -69,8 +74,11 @@ class Channel(auto_prefetch.Model):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    drop_campaigns = models.ManyToManyField(DropCampaign, related_name="channels")
 | 
					    drop_campaigns = models.ManyToManyField(DropCampaign, related_name="channels")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
 | 
					        return self.display_name or "Channel name unknown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TimeBasedDrop(auto_prefetch.Model):
 | 
					
 | 
				
			||||||
 | 
					class TimeBasedDrop(models.Model):
 | 
				
			||||||
    """This is the drop we will see on the front end."""
 | 
					    """This is the drop we will see on the front end."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    id = models.TextField(primary_key=True)  # "d5cdf372-502b-11ef-bafd-0a58a9feac02"
 | 
					    id = models.TextField(primary_key=True)  # "d5cdf372-502b-11ef-bafd-0a58a9feac02"
 | 
				
			||||||
@@ -83,10 +91,13 @@ class TimeBasedDrop(auto_prefetch.Model):
 | 
				
			|||||||
    required_minutes_watched = models.PositiveBigIntegerField(null=True)  # "120"
 | 
					    required_minutes_watched = models.PositiveBigIntegerField(null=True)  # "120"
 | 
				
			||||||
    starts_at = models.DateTimeField(null=True)  # "2024-08-11T11:00:00Z"
 | 
					    starts_at = models.DateTimeField(null=True)  # "2024-08-11T11:00:00Z"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    drop_campaign = auto_prefetch.ForeignKey(DropCampaign, on_delete=models.CASCADE, related_name="drops", null=True)
 | 
					    drop_campaign = models.ForeignKey(DropCampaign, on_delete=models.CASCADE, related_name="drops", null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
 | 
					        return self.name or "Drop name unknown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Benefit(auto_prefetch.Model):
 | 
					class Benefit(models.Model):
 | 
				
			||||||
    """This is the benefit we will see on the front end."""
 | 
					    """This is the benefit we will see on the front end."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    id = models.TextField(primary_key=True)  # "d5cdf372-502b-11ef-bafd-0a58a9feac02"
 | 
					    id = models.TextField(primary_key=True)  # "d5cdf372-502b-11ef-bafd-0a58a9feac02"
 | 
				
			||||||
@@ -104,15 +115,18 @@ class Benefit(auto_prefetch.Model):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    name = models.TextField(null=True)  # "Cosmic Nexus Chimera"
 | 
					    name = models.TextField(null=True)  # "Cosmic Nexus Chimera"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    time_based_drop = auto_prefetch.ForeignKey(
 | 
					    time_based_drop = models.ForeignKey(
 | 
				
			||||||
        TimeBasedDrop,
 | 
					        TimeBasedDrop,
 | 
				
			||||||
        on_delete=models.CASCADE,
 | 
					        on_delete=models.CASCADE,
 | 
				
			||||||
        related_name="benefits",
 | 
					        related_name="benefits",
 | 
				
			||||||
        null=True,
 | 
					        null=True,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
 | 
					        return self.name or "Benefit name unknown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RewardCampaign(auto_prefetch.Model):
 | 
					
 | 
				
			||||||
 | 
					class RewardCampaign(models.Model):
 | 
				
			||||||
    """Buy subscriptions to earn rewards."""
 | 
					    """Buy subscriptions to earn rewards."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    id = models.TextField(primary_key=True)  # "dc4ff0b4-4de0-11ef-9ec3-621fb0811846"
 | 
					    id = models.TextField(primary_key=True)  # "dc4ff0b4-4de0-11ef-9ec3-621fb0811846"
 | 
				
			||||||
@@ -130,7 +144,7 @@ class RewardCampaign(auto_prefetch.Model):
 | 
				
			|||||||
    external_url = models.URLField(null=True)  # "https://tv.apple.com/includes/commerce/redeem/code-entry"
 | 
					    external_url = models.URLField(null=True)  # "https://tv.apple.com/includes/commerce/redeem/code-entry"
 | 
				
			||||||
    about_url = models.URLField(null=True)  # "https://blog.twitch.tv/2024/07/26/sub-and-get-apple-tv/"
 | 
					    about_url = models.URLField(null=True)  # "https://blog.twitch.tv/2024/07/26/sub-and-get-apple-tv/"
 | 
				
			||||||
    is_site_wide = models.BooleanField(null=True)  # "True"
 | 
					    is_site_wide = models.BooleanField(null=True)  # "True"
 | 
				
			||||||
    game = auto_prefetch.ForeignKey(Game, on_delete=models.CASCADE, related_name="reward_campaigns", null=True)
 | 
					    game = models.ForeignKey(Game, on_delete=models.CASCADE, related_name="reward_campaigns", null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sub_goal = models.PositiveBigIntegerField(null=True)  # "1"
 | 
					    sub_goal = models.PositiveBigIntegerField(null=True)  # "1"
 | 
				
			||||||
    minute_watched_goal = models.PositiveBigIntegerField(null=True)  # "0"
 | 
					    minute_watched_goal = models.PositiveBigIntegerField(null=True)  # "0"
 | 
				
			||||||
@@ -138,8 +152,11 @@ class RewardCampaign(auto_prefetch.Model):
 | 
				
			|||||||
    # "https://static-cdn.jtvnw.net/twitch-quests-assets/CAMPAIGN/quests_appletv_q3_2024/apple_150x200.png"
 | 
					    # "https://static-cdn.jtvnw.net/twitch-quests-assets/CAMPAIGN/quests_appletv_q3_2024/apple_150x200.png"
 | 
				
			||||||
    image_url = models.URLField(null=True)
 | 
					    image_url = models.URLField(null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
 | 
					        return self.name or "Reward campaign name unknown"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Reward(auto_prefetch.Model):
 | 
					
 | 
				
			||||||
 | 
					class Reward(models.Model):
 | 
				
			||||||
    """This from the RewardCampaign."""
 | 
					    """This from the RewardCampaign."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    id = models.TextField(primary_key=True)  # "dc2e9810-4de0-11ef-9ec3-621fb0811846"
 | 
					    id = models.TextField(primary_key=True)  # "dc2e9810-4de0-11ef-9ec3-621fb0811846"
 | 
				
			||||||
@@ -154,4 +171,7 @@ class Reward(auto_prefetch.Model):
 | 
				
			|||||||
    redemption_instructions = models.TextField(null=True)  # ""
 | 
					    redemption_instructions = models.TextField(null=True)  # ""
 | 
				
			||||||
    redemption_url = models.URLField(null=True)  # "https://tv.apple.com/includes/commerce/redeem/code-entry"
 | 
					    redemption_url = models.URLField(null=True)  # "https://tv.apple.com/includes/commerce/redeem/code-entry"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    campaign = auto_prefetch.ForeignKey(RewardCampaign, on_delete=models.CASCADE, related_name="rewards", null=True)
 | 
					    campaign = models.ForeignKey(RewardCampaign, on_delete=models.CASCADE, related_name="rewards", null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __str__(self) -> str:
 | 
				
			||||||
 | 
					        return self.name or "Reward name unknown"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,14 +11,15 @@
 | 
				
			|||||||
                {% for campaign in reward_campaigns %}
 | 
					                {% for campaign in reward_campaigns %}
 | 
				
			||||||
                    {% include "partials/reward_campaign_card.html" %}
 | 
					                    {% include "partials/reward_campaign_card.html" %}
 | 
				
			||||||
                {% endfor %}
 | 
					                {% endfor %}
 | 
				
			||||||
                <h2>Organizations</h2>
 | 
					                <h2>
 | 
				
			||||||
                {% for org in owners %}
 | 
					                    Drop campaigns -
 | 
				
			||||||
                    <h2 id="org-{{ org.id }}">
 | 
					                    <div class="d-inline text-muted ">{{ games.count }} games</div>
 | 
				
			||||||
                        <a href="#org-{{ org.id }}">{{ org.name }}</a>
 | 
					 | 
				
			||||||
                </h2>
 | 
					                </h2>
 | 
				
			||||||
                    {% for game in org.games.all %}
 | 
					                {% for game in games %}
 | 
				
			||||||
 | 
					                    {# Only show games with drop campaigns #}
 | 
				
			||||||
 | 
					                    {% if game.drop_campaigns.count > 0 %}
 | 
				
			||||||
                        {% include "partials/game_card.html" %}
 | 
					                        {% include "partials/game_card.html" %}
 | 
				
			||||||
                    {% endfor %}
 | 
					                    {% endif %}
 | 
				
			||||||
                {% endfor %}
 | 
					                {% endfor %}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
<div class="card mb-4 shadow-sm" id="game-{{ game.twitch_id }}">
 | 
					<div class="card mb-4 shadow-sm" id="#{{ game.twitch_id }}">
 | 
				
			||||||
    <div class="row g-0">
 | 
					    <div class="row g-0">
 | 
				
			||||||
        <div class="col-md-2">
 | 
					        <div class="col-md-2">
 | 
				
			||||||
            <img src="https://static-cdn.jtvnw.net/ttv-boxart/{{ game.twitch_id }}_IGDB.jpg"
 | 
					            <img src="https://static-cdn.jtvnw.net/ttv-boxart/{{ game.twitch_id }}_IGDB.jpg"
 | 
				
			||||||
                 alt="{{ game.display_name }}"
 | 
					                 alt="{{ game.name }} box art"
 | 
				
			||||||
                 class="img-fluid rounded-start"
 | 
					                 class="img-fluid rounded-start"
 | 
				
			||||||
                 height="283"
 | 
					                 height="283"
 | 
				
			||||||
                 width="212"
 | 
					                 width="212"
 | 
				
			||||||
@@ -21,11 +21,18 @@
 | 
				
			|||||||
                    {% if not forloop.first %}<br>{% endif %}
 | 
					                    {% if not forloop.first %}<br>{% endif %}
 | 
				
			||||||
                    <div class="mt-3">
 | 
					                    <div class="mt-3">
 | 
				
			||||||
                        <h3 class="h6">{{ campaign.name }}</h3>
 | 
					                        <h3 class="h6">{{ campaign.name }}</h3>
 | 
				
			||||||
 | 
					                        {% if campaign.details_url == campaign.account_link_url %}
 | 
				
			||||||
 | 
					                            <a href="{{ campaign.details_url }}" class="text-decoration-none">Details</a>
 | 
				
			||||||
 | 
					                        {% else %}
 | 
				
			||||||
 | 
					                            <a href="{{ campaign.details_url }}" class="text-decoration-none">Details</a>
 | 
				
			||||||
 | 
					                            |
 | 
				
			||||||
 | 
					                            <a href="{{ campaign.account_link_url }}" class="text-decoration-none">Link Account</a>
 | 
				
			||||||
 | 
					                        {% endif %}
 | 
				
			||||||
                        <p class="mb-2 text-muted">
 | 
					                        <p class="mb-2 text-muted">
 | 
				
			||||||
                            Ends in: <abbr title="{{ campaign.starts_at|date:'l d F H:i' }} - {{ campaign.ends_at|date:'l d F H:i e' }}">{{ campaign.ends_at|timeuntil }}</abbr>
 | 
					                            Ends in: <abbr title="{{ campaign.starts_at|date:'l d F H:i' }} - {{ campaign.ends_at|date:'l d F H:i e' }}">{{ campaign.ends_at|timeuntil }}</abbr>
 | 
				
			||||||
                        </p>
 | 
					                        </p>
 | 
				
			||||||
                        {% if campaign.description != campaign.name %}
 | 
					                        {% if campaign.description != campaign.name %}
 | 
				
			||||||
                            {% if campaign.description|length > 200 %}
 | 
					                            {% if campaign.description|length > 300 %}
 | 
				
			||||||
                                <p>
 | 
					                                <p>
 | 
				
			||||||
                                    <a class="btn btn-link p-0 text-muted"
 | 
					                                    <a class="btn btn-link p-0 text-muted"
 | 
				
			||||||
                                       data-bs-toggle="collapse"
 | 
					                                       data-bs-toggle="collapse"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,10 +4,12 @@ import logging
 | 
				
			|||||||
from dataclasses import dataclass
 | 
					from dataclasses import dataclass
 | 
				
			||||||
from typing import TYPE_CHECKING
 | 
					from typing import TYPE_CHECKING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.db.models import Prefetch
 | 
				
			||||||
from django.db.models.manager import BaseManager
 | 
					from django.db.models.manager import BaseManager
 | 
				
			||||||
from django.template.response import TemplateResponse
 | 
					from django.template.response import TemplateResponse
 | 
				
			||||||
 | 
					from django.utils import timezone  # type: ignore  # noqa: PGH003
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from core.models.twitch import Game, Owner, RewardCampaign
 | 
					from core.models.twitch import DropCampaign, Game, RewardCampaign
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if TYPE_CHECKING:
 | 
					if TYPE_CHECKING:
 | 
				
			||||||
    from django.db.models.manager import BaseManager
 | 
					    from django.db.models.manager import BaseManager
 | 
				
			||||||
@@ -57,18 +59,30 @@ def index(request: HttpRequest) -> HttpResponse:
 | 
				
			|||||||
    Returns:
 | 
					    Returns:
 | 
				
			||||||
        HttpResponse: The response object
 | 
					        HttpResponse: The response object
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    reward_campaigns: BaseManager[RewardCampaign] = RewardCampaign.objects.all()
 | 
					    reward_campaigns: BaseManager[RewardCampaign] = (
 | 
				
			||||||
    owners: BaseManager[Owner] = Owner.objects.all()
 | 
					        RewardCampaign.objects.all()
 | 
				
			||||||
 | 
					        .prefetch_related("rewards")
 | 
				
			||||||
 | 
					        .filter(ends_at__gt=timezone.now(), starts_at__lt=timezone.now())
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    future_campaigns: BaseManager[DropCampaign] = DropCampaign.objects.filter(
 | 
				
			||||||
 | 
					        ends_at__gt=timezone.now(),
 | 
				
			||||||
 | 
					        starts_at__lt=timezone.now(),
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    toc: str = build_toc([
 | 
					    games: BaseManager[Game] = Game.objects.all().prefetch_related(
 | 
				
			||||||
        TOCItem(name="Information", toc_id="#info-box"),
 | 
					        Prefetch("drop_campaigns", queryset=future_campaigns.prefetch_related("drops__benefits")),
 | 
				
			||||||
        TOCItem(name="Games", toc_id="#games"),
 | 
					    )
 | 
				
			||||||
    ])
 | 
					    tocs: list[TOCItem] = []
 | 
				
			||||||
 | 
					    for game in games.all():
 | 
				
			||||||
 | 
					        game_name: str = game.name or "<div class='text-muted'>Game name unknown</div>"
 | 
				
			||||||
 | 
					        tocs.append(TOCItem(name=game_name, toc_id=f"#{game.twitch_id}"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context: dict[str, BaseManager[RewardCampaign] | str | BaseManager[Owner]] = {
 | 
					    toc: str = build_toc(tocs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context: dict[str, BaseManager[RewardCampaign] | str | BaseManager[Game]] = {
 | 
				
			||||||
        "reward_campaigns": reward_campaigns,
 | 
					        "reward_campaigns": reward_campaigns,
 | 
				
			||||||
 | 
					        "games": games,
 | 
				
			||||||
        "toc": toc,
 | 
					        "toc": toc,
 | 
				
			||||||
        "owners": owners,
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return TemplateResponse(request=request, template="index.html", context=context)
 | 
					    return TemplateResponse(request=request, template="index.html", context=context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,10 +98,7 @@ def game_view(request: HttpRequest) -> HttpResponse:
 | 
				
			|||||||
    """
 | 
					    """
 | 
				
			||||||
    games: BaseManager[Game] = Game.objects.all()
 | 
					    games: BaseManager[Game] = Game.objects.all()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tocs: list[TOCItem] = [TOCItem(name=game.name, toc_id=game.slug) for game in games if game.name and game.slug]
 | 
					    context: dict[str, BaseManager[Game] | str] = {"games": games}
 | 
				
			||||||
    toc: str = build_toc(tocs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    context: dict[str, BaseManager[Game] | str] = {"games": games, "toc": toc}
 | 
					 | 
				
			||||||
    return TemplateResponse(request=request, template="games.html", context=context)
 | 
					    return TemplateResponse(request=request, template="games.html", context=context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							@@ -315,20 +315,6 @@ tzdata = {version = "*", markers = "sys_platform == \"win32\""}
 | 
				
			|||||||
argon2 = ["argon2-cffi (>=19.1.0)"]
 | 
					argon2 = ["argon2-cffi (>=19.1.0)"]
 | 
				
			||||||
bcrypt = ["bcrypt"]
 | 
					bcrypt = ["bcrypt"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "django-auto-prefetch"
 | 
					 | 
				
			||||||
version = "1.9.0"
 | 
					 | 
				
			||||||
description = "Automatically prefetch foreign key values as needed."
 | 
					 | 
				
			||||||
optional = false
 | 
					 | 
				
			||||||
python-versions = ">=3.8"
 | 
					 | 
				
			||||||
files = [
 | 
					 | 
				
			||||||
    {file = "django_auto_prefetch-1.9.0-py3-none-any.whl", hash = "sha256:2bcc1d4551a952cc73124d339319570392aece390cedffbd9585d94f802eef47"},
 | 
					 | 
				
			||||||
    {file = "django_auto_prefetch-1.9.0.tar.gz", hash = "sha256:b447a0342a734bd3c718f9721598042721edce1a95b81df5b5a167dd0997f347"},
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[package.dependencies]
 | 
					 | 
				
			||||||
django = ">=3.2"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "django-debug-toolbar"
 | 
					name = "django-debug-toolbar"
 | 
				
			||||||
version = "4.4.6"
 | 
					version = "4.4.6"
 | 
				
			||||||
@@ -1217,4 +1203,4 @@ brotli = ["brotli"]
 | 
				
			|||||||
[metadata]
 | 
					[metadata]
 | 
				
			||||||
lock-version = "2.0"
 | 
					lock-version = "2.0"
 | 
				
			||||||
python-versions = "^3.12"
 | 
					python-versions = "^3.12"
 | 
				
			||||||
content-hash = "4efd9a959fea305be05a55cc0041474ab83ba202dc4c55479bb9d2b66387393b"
 | 
					content-hash = "36def17b6380edc474dbfa9cd469124d4ae2d3b0c27ea4fc8cb4c6c54dddb032"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,6 @@ package-mode = false
 | 
				
			|||||||
python = "^3.12"
 | 
					python = "^3.12"
 | 
				
			||||||
discord-webhook = "^1.3.1"
 | 
					discord-webhook = "^1.3.1"
 | 
				
			||||||
django = { version = "^5.1", allow-prereleases = true }
 | 
					django = { version = "^5.1", allow-prereleases = true }
 | 
				
			||||||
django-auto-prefetch = "^1.9.0"
 | 
					 | 
				
			||||||
django-debug-toolbar = "^4.4.6"
 | 
					django-debug-toolbar = "^4.4.6"
 | 
				
			||||||
django-simple-history = "^3.7.0"
 | 
					django-simple-history = "^3.7.0"
 | 
				
			||||||
pillow = "^10.4.0"
 | 
					pillow = "^10.4.0"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
djlint
 | 
					 | 
				
			||||||
pip
 | 
					 | 
				
			||||||
pre-commit
 | 
					 | 
				
			||||||
pytest
 | 
					 | 
				
			||||||
pytest-django
 | 
					 | 
				
			||||||
ruff
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
discord-webhook
 | 
					 | 
				
			||||||
django-auto-prefetch
 | 
					 | 
				
			||||||
django-debug-toolbar
 | 
					 | 
				
			||||||
django-simple-history
 | 
					 | 
				
			||||||
django>=0.0.0.dev0
 | 
					 | 
				
			||||||
hishel
 | 
					 | 
				
			||||||
httpx
 | 
					 | 
				
			||||||
pillow
 | 
					 | 
				
			||||||
platformdirs
 | 
					 | 
				
			||||||
python-dotenv
 | 
					 | 
				
			||||||
sentry-sdk[django]
 | 
					 | 
				
			||||||
undetected-playwright-patch
 | 
					 | 
				
			||||||
whitenoise[brotli]
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user