World Travel Improvements (#925)
* Security Patch Django 5.2.8 * Fix Menus on Safari Browser * Enhance touch support and event handling for emoji picker and dropdown * Add touch and pointer event handling to category selection for better mobile support * Add PWA support for iOS/Safari with touch icons * Refactor event listener for dropdown to use non-capturing 'click' for improved compatibility on Safari * Enhance country and region description fetching from Wikipedia - Refactor `generate_description_view.py` to improve candidate page selection and description retrieval. - Update `CategoryDropdown.svelte` to simplify emoji selection handling and improve dropdown behavior. - Add new translation keys in `en.json` for UI elements related to country descriptions. - Modify `+page.svelte` and `+page.server.ts` in world travel routes to fetch and display country and region descriptions. - Implement a toggle for showing full descriptions in the UI. * Update Unraid installation documentation with improved variable formatting and additional resources * Implement cache invalidation for visited regions and cities to ensure updated visit lists * Add ClusterMap component for enhanced geographical data visualization
This commit is contained in:
@@ -14,6 +14,26 @@ from adventures.models import Location
|
||||
# Cache TTL
|
||||
CACHE_TTL = 60 * 60 * 24 # 1 day
|
||||
|
||||
|
||||
def invalidate_visit_caches_for_region_and_user(region, user):
|
||||
"""Invalidate cached visit lists for a given region and user.
|
||||
|
||||
Removes both the per-region and per-country per-user cache keys so
|
||||
UI calls will refetch updated visited lists.
|
||||
"""
|
||||
try:
|
||||
if region is None or user is None:
|
||||
return
|
||||
# per-region cache
|
||||
cache.delete(f"visits_by_region_{region.id}_{user.id}")
|
||||
# per-country cache (region -> country -> country_code)
|
||||
country_code = getattr(region.country, 'country_code', None)
|
||||
if country_code:
|
||||
cache.delete(f"visits_by_country_{country_code}_{user.id}")
|
||||
except Exception:
|
||||
# Avoid raising cache-related exceptions; best-effort invalidation
|
||||
pass
|
||||
|
||||
@cache_page(CACHE_TTL)
|
||||
@api_view(['GET'])
|
||||
@permission_classes([IsAuthenticated])
|
||||
@@ -138,13 +158,22 @@ class VisitedRegionViewSet(viewsets.ModelViewSet):
|
||||
serializer.is_valid(raise_exception=True)
|
||||
self.perform_create(serializer)
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
# Invalidate caches for this region and its country for the user
|
||||
try:
|
||||
region = serializer.validated_data.get('region')
|
||||
invalidate_visit_caches_for_region_and_user(region, request.user)
|
||||
except Exception:
|
||||
pass
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
def destroy(self, request, **kwargs):
|
||||
region = get_object_or_404(Region, id=kwargs['pk'])
|
||||
visited_region = VisitedRegion.objects.filter(user=request.user.id, region=region)
|
||||
if visited_region.exists():
|
||||
# capture region before deleting so we can invalidate caches
|
||||
affected_region = visited_region.first().region
|
||||
visited_region.delete()
|
||||
invalidate_visit_caches_for_region_and_user(affected_region, request.user)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
else:
|
||||
return Response({"error": "Visited region not found."}, status=status.HTTP_404_NOT_FOUND)
|
||||
@@ -164,9 +193,14 @@ class VisitedCityViewSet(viewsets.ModelViewSet):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
self.perform_create(serializer)
|
||||
# Ensure a VisitedRegion exists for the city and invalidate caches
|
||||
region = serializer.validated_data['city'].region
|
||||
if not VisitedRegion.objects.filter(user=request.user.id, region=region).exists():
|
||||
VisitedRegion.objects.create(user=request.user, region=region)
|
||||
try:
|
||||
invalidate_visit_caches_for_region_and_user(region, request.user)
|
||||
except Exception:
|
||||
pass
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
@@ -174,7 +208,9 @@ class VisitedCityViewSet(viewsets.ModelViewSet):
|
||||
city = get_object_or_404(City, id=kwargs['pk'])
|
||||
visited_city = VisitedCity.objects.filter(user=request.user.id, city=city)
|
||||
if visited_city.exists():
|
||||
region = city.region
|
||||
visited_city.delete()
|
||||
invalidate_visit_caches_for_region_and_user(region, request.user)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
else:
|
||||
return Response({"error": "Visited city not found."}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
Reference in New Issue
Block a user