diff --git a/common/context_processors.py b/common/context_processors.py new file mode 100644 index 0000000..22b6b57 --- /dev/null +++ b/common/context_processors.py @@ -0,0 +1,6 @@ +from django.conf import settings + +def cache_settings(request): + return { + 'CACHE_TIMEOUT': settings.CACHE_TIMEOUT, + } \ No newline at end of file diff --git a/django_project/settings.py b/django_project/settings.py index 8b46e19..dade4b0 100644 --- a/django_project/settings.py +++ b/django_project/settings.py @@ -148,6 +148,7 @@ TEMPLATES = [ "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", + "common.context_processors.cache_settings", ], }, }, @@ -294,6 +295,8 @@ SOCIALACCOUNT_EMAIL_AUTHENTICATION = False SOCIALACCOUNT_EMAIL_AUTHENTICATION_AUTO_CONNECT = False SOCIALACCOUNT_ONLY = False +CACHE_TIMEOUT = 604800 # 1 week + if DEBUG: CACHES = { "default": { @@ -305,5 +308,6 @@ else: "default": { "BACKEND": "django.core.cache.backends.db.DatabaseCache", "LOCATION": "django_cache", + "TIMEOUT": 604800, # 1 week } } diff --git a/home/views.py b/home/views.py index f931397..28dd8a9 100644 --- a/home/views.py +++ b/home/views.py @@ -12,6 +12,7 @@ from django.http import HttpResponseRedirect import logging from django.views import View from django.http import HttpResponse +import contextlib logger = logging.getLogger(__name__) @@ -31,46 +32,54 @@ class HomePageView(TemplateView): # Recent Offers try: - recent_offers_qs = base_offer_qs.order_by("-created_at") - context["recent_offers"] = recent_offers_qs[:6] + recent_offers_qs = base_offer_qs.order_by("-created_at")[:6] + context["recent_offers"] = recent_offers_qs + context["cache_key_recent_offers"] = f"recent_offers_{recent_offers_qs.values_list('pk', 'updated_at')}" except Exception as e: logger.error(f"Error fetching recent offers: {str(e)}") context["recent_offers"] = [] + context["cache_key_recent_offers"] = "recent_offers_error" # Most Offered Cards try: - context["most_offered_cards"] = ( + most_offered_cards_qs = ( Card.objects.filter(tradeofferhavecard__isnull=False).filter(rarity_level__lte=5) .annotate(offer_count=Sum("tradeofferhavecard__quantity")) .order_by("-offer_count")[:6] ) + context["most_offered_cards"] = most_offered_cards_qs + context["cache_key_most_offered_cards"] = f"most_offered_cards_{most_offered_cards_qs.values_list('pk', 'updated_at')}" except Exception as e: logger.error(f"Error fetching most offered cards: {str(e)}") context["most_offered_cards"] = [] - + context["cache_key_most_offered_cards"] = "most_offered_cards_error" # Most Wanted Cards try: - context["most_wanted_cards"] = ( + most_wanted_cards_qs = ( Card.objects.filter(tradeofferwantcard__isnull=False).filter(rarity_level__lte=5) .annotate(offer_count=Sum("tradeofferwantcard__quantity")) .order_by("-offer_count")[:6] ) + context["most_wanted_cards"] = most_wanted_cards_qs + context["cache_key_most_wanted_cards"] = f"most_wanted_cards_{most_wanted_cards_qs.values_list('pk', 'updated_at')}" except Exception as e: logger.error(f"Error fetching most wanted cards: {str(e)}") context["most_wanted_cards"] = [] # Least Offered Cards try: - context["least_offered_cards"] = ( + least_offered_cards_qs = ( Card.objects.filter(rarity_level__lte=5).annotate( offer_count=Coalesce(Sum("tradeofferhavecard__quantity"), 0) ) .order_by("offer_count")[:6] ) + context["least_offered_cards"] = least_offered_cards_qs + context["cache_key_least_offered_cards"] = f"least_offered_cards_{least_offered_cards_qs.values_list('pk', 'updated_at')}" except Exception as e: logger.error(f"Error fetching least offered cards: {str(e)}") context["least_offered_cards"] = [] - + context["cache_key_least_offered_cards"] = "least_offered_cards_error" # Build featured offers with custom ordering featured = OrderedDict() # Featured "All" offers remains fixed at the top @@ -100,10 +109,22 @@ class HomePageView(TemplateView): logger.error(f"Error processing rarity-based featured offers: {str(e)}") context["featured_offers"] = featured + # Generate a cache key based on the pks and updated_at timestamps of all featured offers + all_offer_identifiers = [] + for section_name,section_offers in featured.items(): + # featured_section is a QuerySet. Fetch (pk, updated_at) tuples. + identifiers = section_offers.values_list('pk', 'updated_at') + # Format each tuple as "pk_timestamp" and add to the list + section_strings = [f"{section_name}_{pk}_{ts.timestamp()}" for pk, ts in identifiers] + all_offer_identifiers.extend(section_strings) + + # Join all identifiers into a single string, sorted for consistency regardless of order + combined_identifiers = "|".join(sorted(all_offer_identifiers)) + context["cache_key_featured_offers"] = f"featured_offers_{combined_identifiers}" except Exception as e: logger.error(f"Unhandled error in HomePageView.get_context_data: {str(e)}") # Provide fallback empty data - context["cards"] = [] + context["cards"] = None context["recent_offers"] = [] context["most_offered_cards"] = [] context["most_wanted_cards"] = [] @@ -118,4 +139,27 @@ class HomePageView(TemplateView): class HealthCheckView(View): def get(self, request, *args, **kwargs): + + try: + from django.db import connection + connection.cursor().execute("SELECT 1") + except Exception as e: + return HttpResponse("Database connection failed", status=500) + + try: + from trades.models import TradeOffer + with contextlib.redirect_stdout(None): + print(TradeOffer.objects.count()) + except Exception as e: + return HttpResponse("DB models not reachable, but db is reachable", status=500) + + try: + from django.core.cache import cache + cache.set("test", "test") + with contextlib.redirect_stdout(None): + print(cache.get("test")) + except Exception as e: + return HttpResponse("Cache not reachable", status=500) + + logger.info("OK/HEALTHY") return HttpResponse("OK/HEALTHY") diff --git a/theme/templates/home/home.html b/theme/templates/home/home.html index 025c681..f2eca0b 100644 --- a/theme/templates/home/home.html +++ b/theme/templates/home/home.html @@ -41,44 +41,44 @@