From 0ee6e8c82056704d2d37368cf53595aec5601d65 Mon Sep 17 00:00:00 2001 From: pac7 <47831526-pac7@users.noreply.replit.com> Date: Mon, 22 Sep 2025 14:36:17 +0000 Subject: [PATCH] Ensure park and ride slugs are valid before displaying links Prevents 500 errors by filtering out parks and rides with null or empty slugs from trending lists and excludes them from database queries where slugs are required. Additionally, it adds conditional rendering in templates to handle parks without slugs gracefully. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 0bdea3fb-49ea-4863-b501-fa6f5af0cbf0 Replit-Commit-Checkpoint-Type: intermediate_checkpoint --- .replit | 4 - ...e-packages-1758551531707_1758551531707.txt | 116 ++++++++++++++++++ static/css/tailwind.css | 75 ----------- templates/cotton/park_card.html | 28 +++-- templates/home.html | 93 +------------- thrillwiki/views.py | 24 ++-- 6 files changed, 155 insertions(+), 185 deletions(-) create mode 100644 attached_assets/Pasted-Traceback-most-recent-call-last-File-home-runner-workspace-venv-lib-python3-13-site-packages-1758551531707_1758551531707.txt diff --git a/.replit b/.replit index 5bd91547..3520ba63 100644 --- a/.replit +++ b/.replit @@ -54,10 +54,6 @@ outputType = "webview" localPort = 5000 externalPort = 80 -[[ports]] -localPort = 37689 -externalPort = 3002 - [[ports]] localPort = 41923 externalPort = 3000 diff --git a/attached_assets/Pasted-Traceback-most-recent-call-last-File-home-runner-workspace-venv-lib-python3-13-site-packages-1758551531707_1758551531707.txt b/attached_assets/Pasted-Traceback-most-recent-call-last-File-home-runner-workspace-venv-lib-python3-13-site-packages-1758551531707_1758551531707.txt new file mode 100644 index 00000000..d99eb1aa --- /dev/null +++ b/attached_assets/Pasted-Traceback-most-recent-call-last-File-home-runner-workspace-venv-lib-python3-13-site-packages-1758551531707_1758551531707.txt @@ -0,0 +1,116 @@ +Traceback (most recent call last): + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/contrib/staticfiles/handlers.py", line 80, in __call__ + return self.application(environ, start_response) + ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/core/handlers/wsgi.py", line 124, in __call__ + response = self.get_response(request) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 140, in get_response + response = self._middleware_chain(request) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 57, in inner + response = response_for_exception(request, exc) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 141, in response_for_exception + response = handle_uncaught_exception( + + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 182, in handle_uncaught_exception + return debug.technical_500_response(request, *exc_info) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django_extensions/management/technical_response.py", line 41, in null_technical_500_response + raise exc_value.with_traceback(tb) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner + response = get_response(request) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 220, in _get_response + response = response.render() + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/response.py", line 114, in render + self.content = self.rendered_content + ^^^^^^^^^^^^^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/response.py", line 92, in rendered_content + return template.render(context, self._request) + ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/backends/django.py", line 107, in render + return self.template.render(context) + ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 171, in render + return self._render(context) + ~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/loader_tags.py", line 159, in render + return compiled_parent._render(context) + ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/loader_tags.py", line 65, in render + result = block.nodelist.render(context) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/defaulttags.py", line 243, in render + nodelist.append(node.render_annotated(context)) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django_cotton/templatetags/_component.py", line 86, in render + output = template.render(context) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 173, in render + return self._render(context) + ~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 163, in _render + return self.nodelist.render(context) + ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django_cotton/templatetags/_vars.py", line 52, in render + output = self.nodelist.render(context) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/defaulttags.py", line 327, in render + return nodelist.render(context) + ~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 1016, in render + return SafeString("".join([node.render_annotated(context) for node in self])) + ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/base.py", line 977, in render_annotated + return self.render(context) + ~~~~~~~~~~~^^^^^^^^^ + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/template/defaulttags.py", line 480, in render + url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/urls/base.py", line 98, in reverse + resolved_url = resolver._reverse_with_prefix(view, prefix, *args, **kwargs) + File "/home/runner/workspace/.venv/lib/python3.13/site-packages/django/urls/resolvers.py", line 831, in _reverse_with_prefix + raise NoReverseMatch(msg) +django.urls.exceptions.NoReverseMatch: Reverse for 'park_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['parks/(?P[-a-zA-Z0-9_]+)/\\Z'] \ No newline at end of file diff --git a/static/css/tailwind.css b/static/css/tailwind.css index 590d1485..a9f01a54 100644 --- a/static/css/tailwind.css +++ b/static/css/tailwind.css @@ -410,9 +410,6 @@ .top-0 { top: calc(var(--spacing) * 0); } - .top-1 { - top: calc(var(--spacing) * 1); - } .top-1\/2 { top: calc(1/2 * 100%); } @@ -452,9 +449,6 @@ .left-0 { left: calc(var(--spacing) * 0); } - .left-1 { - left: calc(var(--spacing) * 1); - } .left-1\/2 { left: calc(1/2 * 100%); } @@ -533,9 +527,6 @@ max-width: 96rem; } } - .-mx-1 { - margin-inline: calc(var(--spacing) * -1); - } .-mx-1\.5 { margin-inline: calc(var(--spacing) * -1.5); } @@ -554,9 +545,6 @@ .mx-auto { margin-inline: auto; } - .-my-1 { - margin-block: calc(var(--spacing) * -1); - } .-my-1\.5 { margin-block: calc(var(--spacing) * -1.5); } @@ -566,9 +554,6 @@ .my-auto { margin-block: auto; } - .mt-0 { - margin-top: calc(var(--spacing) * 0); - } .mt-0\.5 { margin-top: calc(var(--spacing) * 0.5); } @@ -641,9 +626,6 @@ .mb-12 { margin-bottom: calc(var(--spacing) * 12); } - .-ml-0 { - margin-left: calc(var(--spacing) * -0); - } .-ml-0\.5 { margin-left: calc(var(--spacing) * -0.5); } @@ -815,9 +797,6 @@ .min-h-screen { min-height: 100vh; } - .w-1 { - width: calc(var(--spacing) * 1); - } .w-1\/2 { width: calc(1/2 * 100%); } @@ -953,13 +932,6 @@ .grow { flex-grow: 1; } - .border-collapse { - border-collapse: collapse; - } - .-translate-x-1 { - --tw-translate-x: calc(var(--spacing) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } .-translate-x-1\/2 { --tw-translate-x: calc(calc(1/2 * 100%) * -1); translate: var(--tw-translate-x) var(--tw-translate-y); @@ -976,10 +948,6 @@ --tw-translate-x: 100%; translate: var(--tw-translate-x) var(--tw-translate-y); } - .-translate-y-1 { - --tw-translate-y: calc(var(--spacing) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } .-translate-y-1\/2 { --tw-translate-y: calc(calc(1/2 * 100%) * -1); translate: var(--tw-translate-x) var(--tw-translate-y); @@ -1162,13 +1130,6 @@ margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse))); } } - .space-y-8 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse))); - } - } .-space-x-px { :where(& > :not(:last-child)) { --tw-space-x-reverse: 0; @@ -1433,9 +1394,6 @@ .bg-\[\#5865F2\] { background-color: #5865F2; } - .bg-accent { - background-color: var(--color-accent); - } .bg-accent\/10 { background-color: color-mix(in srgb, #8b5cf6 10%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1484,9 +1442,6 @@ .bg-blue-600 { background-color: var(--color-blue-600); } - .bg-blue-900 { - background-color: var(--color-blue-900); - } .bg-blue-900\/40 { background-color: color-mix(in srgb, oklch(37.9% 0.146 265.522) 40%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1541,9 +1496,6 @@ .bg-green-600 { background-color: var(--color-green-600); } - .bg-green-900 { - background-color: var(--color-green-900); - } .bg-green-900\/40 { background-color: color-mix(in srgb, oklch(39.3% 0.095 152.535) 40%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1598,9 +1550,6 @@ .bg-red-600 { background-color: var(--color-red-600); } - .bg-red-900 { - background-color: var(--color-red-900); - } .bg-red-900\/40 { background-color: color-mix(in srgb, oklch(39.6% 0.141 25.723) 40%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1658,9 +1607,6 @@ .bg-yellow-600 { background-color: var(--color-yellow-600); } - .bg-yellow-900 { - background-color: var(--color-yellow-900); - } .bg-yellow-900\/40 { background-color: color-mix(in srgb, oklch(42.1% 0.095 57.708) 40%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1679,10 +1625,6 @@ --tw-gradient-position: to top in oklab; background-image: linear-gradient(var(--tw-gradient-stops)); } - .from-black { - --tw-gradient-from: var(--color-black); - --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); - } .from-black\/60 { --tw-gradient-from: color-mix(in srgb, #000 60%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1743,10 +1685,6 @@ --tw-gradient-from: var(--color-red-500); --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); } - .from-secondary { - --tw-gradient-from: var(--color-secondary); - --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); - } .from-secondary\/20 { --tw-gradient-from: color-mix(in srgb, #e11d48 20%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1782,10 +1720,6 @@ --tw-gradient-via-stops: var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position); --tw-gradient-stops: var(--tw-gradient-via-stops); } - .to-accent { - --tw-gradient-to: var(--color-accent); - --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); - } .to-accent\/20 { --tw-gradient-to: color-mix(in srgb, #8b5cf6 20%, transparent); @supports (color: color-mix(in lab, red, red)) { @@ -1915,9 +1849,6 @@ .px-8 { padding-inline: calc(var(--spacing) * 8); } - .py-0 { - padding-block: calc(var(--spacing) * 0); - } .py-0\.5 { padding-block: calc(var(--spacing) * 0.5); } @@ -2122,9 +2053,6 @@ .text-emerald-800 { color: var(--color-emerald-800); } - .text-gray-200 { - color: var(--color-gray-200); - } .text-gray-300 { color: var(--color-gray-300); } @@ -2254,9 +2182,6 @@ .italic { font-style: italic; } - .underline { - text-decoration-line: underline; - } .underline-offset-4 { text-underline-offset: 4px; } diff --git a/templates/cotton/park_card.html b/templates/cotton/park_card.html index ed8a4c8b..73fe0ee5 100644 --- a/templates/cotton/park_card.html +++ b/templates/cotton/park_card.html @@ -56,10 +56,16 @@ Features:

- - {{ park.name }} - + {% if park.slug %} + + {{ park.name }} + + {% else %} + + {{ park.name }} + + {% endif %}

{# Status Badge #} @@ -123,10 +129,16 @@ Features:

- - {{ park.name }} - + {% if park.slug %} + + {{ park.name }} + + {% else %} + + {{ park.name }} + + {% endif %}

{# Status Badge #} diff --git a/templates/home.html b/templates/home.html index e29c7aaf..70aa62dd 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,5 +1,6 @@ {% extends 'base/base.html' %} {% load static %} +{% load cotton %} {% block title %}ThrillWiki - Theme Parks & Attractions Guide{% endblock %} @@ -71,30 +72,7 @@
{% for park in popular_parks %} - -
-
- {{ park.name }} -
-
- {{ park.ride_count }} rides, {{ park.coaster_count }} coasters -
- {% if park.average_rating %} -
- - {{ park.average_rating|floatformat:1 }}/10 -
- {% else %} -
Rating not available
- {% endif %} -
-
+ {% empty %}
🎢
@@ -112,30 +90,7 @@
{% for ride in popular_rides %} - -
-
- {{ ride.name }} -
-
- at {{ ride.park.name }} -
- {% if ride.average_rating %} -
- - {{ ride.average_rating|floatformat:1 }}/10 -
- {% else %} -
Rating not available
- {% endif %} -
-
+ {% empty %}
🎠
@@ -155,48 +110,10 @@ {% for item in highest_rated %} {% if item.park %} - -
-
- {{ item.name }} -
-
- at {{ item.park.name }} -
-
- - {{ item.average_rating|floatformat:1 }}/10 -
-
-
+ {% else %} - -
-
- {{ item.name }} -
-
- {{ item.ride_count }} rides, {{ item.coaster_count }} coasters -
-
- - {{ item.average_rating|floatformat:1 }}/10 -
-
-
+ {% endif %} {% empty %}
diff --git a/thrillwiki/views.py b/thrillwiki/views.py index e0a436c9..7618ac6f 100644 --- a/thrillwiki/views.py +++ b/thrillwiki/views.py @@ -41,6 +41,8 @@ class HomeView(TemplateView): trending_parks = list( PageView.get_trending_items(Park, hours=24, limit=10) ) + # Filter out any parks with invalid slugs + trending_parks = [p for p in trending_parks if getattr(p, 'slug', None)] if trending_parks: cache.set( "trending_parks", trending_parks, 3600 @@ -49,18 +51,20 @@ class HomeView(TemplateView): # Fallback to highest rated parks if no trending data trending_parks = Park.objects.exclude( average_rating__isnull=True - ).order_by("-average_rating")[:10] + ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10] except Exception: # Fallback to highest rated parks if trending calculation fails trending_parks = Park.objects.exclude( average_rating__isnull=True - ).order_by("-average_rating")[:10] + ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10] if trending_rides is None: try: trending_rides = list( PageView.get_trending_items(Ride, hours=24, limit=10) ) + # Filter out any rides with invalid slugs + trending_rides = [r for r in trending_rides if getattr(r, 'slug', None)] if trending_rides: cache.set( "trending_rides", trending_rides, 3600 @@ -69,24 +73,24 @@ class HomeView(TemplateView): # Fallback to highest rated rides if no trending data trending_rides = Ride.objects.exclude( average_rating__isnull=True - ).order_by("-average_rating")[:10] + ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10] except Exception: # Fallback to highest rated rides if trending calculation fails trending_rides = Ride.objects.exclude( average_rating__isnull=True - ).order_by("-average_rating")[:10] + ).exclude(slug__isnull=True).exclude(slug__exact='').order_by("-average_rating")[:10] # Get highest rated items (mix of parks and rides) highest_rated_parks = list( - Park.objects.exclude(average_rating__isnull=True).order_by( - "-average_rating" - )[:20] + Park.objects.exclude(average_rating__isnull=True) + .exclude(slug__isnull=True).exclude(slug__exact='') + .order_by("-average_rating")[:20] ) # Get more items to randomly select from highest_rated_rides = list( - Ride.objects.exclude(average_rating__isnull=True).order_by( - "-average_rating" - )[:20] + Ride.objects.exclude(average_rating__isnull=True) + .exclude(slug__isnull=True).exclude(slug__exact='') + .order_by("-average_rating")[:20] ) # Get more items to randomly select from # Combine and shuffle highest rated items