Make index view faster

This commit is contained in:
2024-08-13 05:37:53 +02:00
parent edbdc9aa32
commit 041b2ddb95
11 changed files with 146 additions and 257 deletions

View File

@ -17,6 +17,7 @@
"sitewide", "sitewide",
"socialaccount", "socialaccount",
"Stresss", "Stresss",
"tocs",
"ttvdrops", "ttvdrops",
"ulimits", "ulimits",
"Valair", "Valair",

View File

@ -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,
},
), ),
] ]

View File

@ -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",
),
),
]

View File

@ -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"

View File

@ -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>

View File

@ -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"

View File

@ -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
View File

@ -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"

View File

@ -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"

View File

@ -1,6 +0,0 @@
djlint
pip
pre-commit
pytest
pytest-django
ruff

View File

@ -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]