mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-21 09:11:08 -05:00
Refactor test utilities and enhance ASGI settings
- Cleaned up and standardized assertions in ApiTestMixin for API response validation. - Updated ASGI settings to use os.environ for setting the DJANGO_SETTINGS_MODULE. - Removed unused imports and improved formatting in settings.py. - Refactored URL patterns in urls.py for better readability and organization. - Enhanced view functions in views.py for consistency and clarity. - Added .flake8 configuration for linting and style enforcement. - Introduced type stubs for django-environ to improve type checking with Pylance.
This commit is contained in:
@@ -3,8 +3,8 @@ Selectors for park-related data retrieval.
|
||||
Following Django styleguide pattern for separating data access from business logic.
|
||||
"""
|
||||
|
||||
from typing import Optional, Dict, Any, List
|
||||
from django.db.models import QuerySet, Q, F, Count, Avg, Prefetch
|
||||
from typing import Optional, Dict, Any
|
||||
from django.db.models import QuerySet, Q, Count, Avg, Prefetch
|
||||
from django.contrib.gis.geos import Point
|
||||
from django.contrib.gis.measure import Distance
|
||||
|
||||
@@ -15,230 +15,234 @@ from rides.models import Ride
|
||||
def park_list_with_stats(*, filters: Optional[Dict[str, Any]] = None) -> QuerySet[Park]:
|
||||
"""
|
||||
Get parks optimized for list display with basic stats.
|
||||
|
||||
|
||||
Args:
|
||||
filters: Optional dictionary of filter parameters
|
||||
|
||||
|
||||
Returns:
|
||||
QuerySet of parks with optimized queries
|
||||
"""
|
||||
queryset = Park.objects.select_related(
|
||||
'operator',
|
||||
'property_owner'
|
||||
).prefetch_related(
|
||||
'location'
|
||||
).annotate(
|
||||
ride_count_calculated=Count('rides', distinct=True),
|
||||
coaster_count_calculated=Count(
|
||||
'rides',
|
||||
filter=Q(rides__category__in=['RC', 'WC']),
|
||||
distinct=True
|
||||
),
|
||||
average_rating_calculated=Avg('reviews__rating')
|
||||
queryset = (
|
||||
Park.objects.select_related("operator", "property_owner")
|
||||
.prefetch_related("location")
|
||||
.annotate(
|
||||
ride_count_calculated=Count("rides", distinct=True),
|
||||
coaster_count_calculated=Count(
|
||||
"rides",
|
||||
filter=Q(rides__category__in=["RC", "WC"]),
|
||||
distinct=True,
|
||||
),
|
||||
average_rating_calculated=Avg("reviews__rating"),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if filters:
|
||||
if 'status' in filters:
|
||||
queryset = queryset.filter(status=filters['status'])
|
||||
if 'operator' in filters:
|
||||
queryset = queryset.filter(operator=filters['operator'])
|
||||
if 'country' in filters:
|
||||
queryset = queryset.filter(location__country=filters['country'])
|
||||
if 'search' in filters:
|
||||
search_term = filters['search']
|
||||
if "status" in filters:
|
||||
queryset = queryset.filter(status=filters["status"])
|
||||
if "operator" in filters:
|
||||
queryset = queryset.filter(operator=filters["operator"])
|
||||
if "country" in filters:
|
||||
queryset = queryset.filter(location__country=filters["country"])
|
||||
if "search" in filters:
|
||||
search_term = filters["search"]
|
||||
queryset = queryset.filter(
|
||||
Q(name__icontains=search_term) |
|
||||
Q(description__icontains=search_term)
|
||||
Q(name__icontains=search_term) | Q(description__icontains=search_term)
|
||||
)
|
||||
|
||||
return queryset.order_by('name')
|
||||
|
||||
return queryset.order_by("name")
|
||||
|
||||
|
||||
def park_detail_optimized(*, slug: str) -> Park:
|
||||
"""
|
||||
Get a single park with all related data optimized for detail view.
|
||||
|
||||
|
||||
Args:
|
||||
slug: Park slug identifier
|
||||
|
||||
|
||||
Returns:
|
||||
Park instance with optimized prefetches
|
||||
|
||||
|
||||
Raises:
|
||||
Park.DoesNotExist: If park with slug doesn't exist
|
||||
"""
|
||||
return Park.objects.select_related(
|
||||
'operator',
|
||||
'property_owner'
|
||||
).prefetch_related(
|
||||
'location',
|
||||
'areas',
|
||||
Prefetch(
|
||||
'rides',
|
||||
queryset=Ride.objects.select_related('manufacturer', 'designer', 'ride_model')
|
||||
),
|
||||
Prefetch(
|
||||
'reviews',
|
||||
queryset=ParkReview.objects.select_related('user').filter(is_published=True)
|
||||
),
|
||||
'photos'
|
||||
).get(slug=slug)
|
||||
return (
|
||||
Park.objects.select_related("operator", "property_owner")
|
||||
.prefetch_related(
|
||||
"location",
|
||||
"areas",
|
||||
Prefetch(
|
||||
"rides",
|
||||
queryset=Ride.objects.select_related(
|
||||
"manufacturer", "designer", "ride_model"
|
||||
),
|
||||
),
|
||||
Prefetch(
|
||||
"reviews",
|
||||
queryset=ParkReview.objects.select_related("user").filter(
|
||||
is_published=True
|
||||
),
|
||||
),
|
||||
"photos",
|
||||
)
|
||||
.get(slug=slug)
|
||||
)
|
||||
|
||||
|
||||
def parks_near_location(
|
||||
*,
|
||||
point: Point,
|
||||
distance_km: float = 50,
|
||||
limit: int = 10
|
||||
*, point: Point, distance_km: float = 50, limit: int = 10
|
||||
) -> QuerySet[Park]:
|
||||
"""
|
||||
Get parks near a specific geographic location.
|
||||
|
||||
|
||||
Args:
|
||||
point: Geographic point (longitude, latitude)
|
||||
distance_km: Maximum distance in kilometers
|
||||
limit: Maximum number of results
|
||||
|
||||
|
||||
Returns:
|
||||
QuerySet of nearby parks ordered by distance
|
||||
"""
|
||||
return Park.objects.filter(
|
||||
location__coordinates__distance_lte=(point, Distance(km=distance_km))
|
||||
).select_related(
|
||||
'operator'
|
||||
).prefetch_related(
|
||||
'location'
|
||||
).distance(point).order_by('distance')[:limit]
|
||||
return (
|
||||
Park.objects.filter(
|
||||
location__coordinates__distance_lte=(
|
||||
point,
|
||||
Distance(km=distance_km),
|
||||
)
|
||||
)
|
||||
.select_related("operator")
|
||||
.prefetch_related("location")
|
||||
.distance(point)
|
||||
.order_by("distance")[:limit]
|
||||
)
|
||||
|
||||
|
||||
def park_statistics() -> Dict[str, Any]:
|
||||
"""
|
||||
Get overall park statistics for dashboard/analytics.
|
||||
|
||||
|
||||
Returns:
|
||||
Dictionary containing park statistics
|
||||
"""
|
||||
total_parks = Park.objects.count()
|
||||
operating_parks = Park.objects.filter(status='OPERATING').count()
|
||||
operating_parks = Park.objects.filter(status="OPERATING").count()
|
||||
total_rides = Ride.objects.count()
|
||||
total_coasters = Ride.objects.filter(category__in=['RC', 'WC']).count()
|
||||
|
||||
total_coasters = Ride.objects.filter(category__in=["RC", "WC"]).count()
|
||||
|
||||
return {
|
||||
'total_parks': total_parks,
|
||||
'operating_parks': operating_parks,
|
||||
'closed_parks': total_parks - operating_parks,
|
||||
'total_rides': total_rides,
|
||||
'total_coasters': total_coasters,
|
||||
'average_rides_per_park': total_rides / total_parks if total_parks > 0 else 0
|
||||
"total_parks": total_parks,
|
||||
"operating_parks": operating_parks,
|
||||
"closed_parks": total_parks - operating_parks,
|
||||
"total_rides": total_rides,
|
||||
"total_coasters": total_coasters,
|
||||
"average_rides_per_park": (total_rides / total_parks if total_parks > 0 else 0),
|
||||
}
|
||||
|
||||
|
||||
def parks_by_operator(*, operator_id: int) -> QuerySet[Park]:
|
||||
"""
|
||||
Get all parks operated by a specific company.
|
||||
|
||||
|
||||
Args:
|
||||
operator_id: Company ID of the operator
|
||||
|
||||
|
||||
Returns:
|
||||
QuerySet of parks operated by the company
|
||||
"""
|
||||
return Park.objects.filter(
|
||||
operator_id=operator_id
|
||||
).select_related(
|
||||
'operator'
|
||||
).prefetch_related(
|
||||
'location'
|
||||
).annotate(
|
||||
ride_count_calculated=Count('rides')
|
||||
).order_by('name')
|
||||
return (
|
||||
Park.objects.filter(operator_id=operator_id)
|
||||
.select_related("operator")
|
||||
.prefetch_related("location")
|
||||
.annotate(ride_count_calculated=Count("rides"))
|
||||
.order_by("name")
|
||||
)
|
||||
|
||||
|
||||
def parks_with_recent_reviews(*, days: int = 30) -> QuerySet[Park]:
|
||||
"""
|
||||
Get parks that have received reviews in the last N days.
|
||||
|
||||
|
||||
Args:
|
||||
days: Number of days to look back for reviews
|
||||
|
||||
|
||||
Returns:
|
||||
QuerySet of parks with recent reviews
|
||||
"""
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
cutoff_date = timezone.now() - timedelta(days=days)
|
||||
|
||||
return Park.objects.filter(
|
||||
reviews__created_at__gte=cutoff_date,
|
||||
reviews__is_published=True
|
||||
).select_related(
|
||||
'operator'
|
||||
).prefetch_related(
|
||||
'location'
|
||||
).annotate(
|
||||
recent_review_count=Count('reviews', filter=Q(reviews__created_at__gte=cutoff_date))
|
||||
).order_by('-recent_review_count').distinct()
|
||||
|
||||
return (
|
||||
Park.objects.filter(
|
||||
reviews__created_at__gte=cutoff_date, reviews__is_published=True
|
||||
)
|
||||
.select_related("operator")
|
||||
.prefetch_related("location")
|
||||
.annotate(
|
||||
recent_review_count=Count(
|
||||
"reviews", filter=Q(reviews__created_at__gte=cutoff_date)
|
||||
)
|
||||
)
|
||||
.order_by("-recent_review_count")
|
||||
.distinct()
|
||||
)
|
||||
|
||||
|
||||
def park_search_autocomplete(*, query: str, limit: int = 10) -> QuerySet[Park]:
|
||||
"""
|
||||
Get parks matching a search query for autocomplete functionality.
|
||||
|
||||
|
||||
Args:
|
||||
query: Search string
|
||||
limit: Maximum number of results
|
||||
|
||||
|
||||
Returns:
|
||||
QuerySet of matching parks for autocomplete
|
||||
"""
|
||||
return Park.objects.filter(
|
||||
Q(name__icontains=query) |
|
||||
Q(location__city__icontains=query) |
|
||||
Q(location__region__icontains=query)
|
||||
).select_related(
|
||||
'operator'
|
||||
).prefetch_related(
|
||||
'location'
|
||||
).order_by('name')[:limit]
|
||||
return (
|
||||
Park.objects.filter(
|
||||
Q(name__icontains=query)
|
||||
| Q(location__city__icontains=query)
|
||||
| Q(location__region__icontains=query)
|
||||
)
|
||||
.select_related("operator")
|
||||
.prefetch_related("location")
|
||||
.order_by("name")[:limit]
|
||||
)
|
||||
|
||||
|
||||
def park_areas_for_park(*, park_slug: str) -> QuerySet[ParkArea]:
|
||||
"""
|
||||
Get all areas for a specific park.
|
||||
|
||||
|
||||
Args:
|
||||
park_slug: Slug of the park
|
||||
|
||||
|
||||
Returns:
|
||||
QuerySet of park areas with related data
|
||||
"""
|
||||
return ParkArea.objects.filter(
|
||||
park__slug=park_slug
|
||||
).select_related(
|
||||
'park'
|
||||
).prefetch_related(
|
||||
'rides'
|
||||
).annotate(
|
||||
ride_count=Count('rides')
|
||||
).order_by('name')
|
||||
return (
|
||||
ParkArea.objects.filter(park__slug=park_slug)
|
||||
.select_related("park")
|
||||
.prefetch_related("rides")
|
||||
.annotate(ride_count=Count("rides"))
|
||||
.order_by("name")
|
||||
)
|
||||
|
||||
|
||||
def park_reviews_for_park(*, park_id: int, limit: int = 20) -> QuerySet[ParkReview]:
|
||||
"""
|
||||
Get reviews for a specific park.
|
||||
|
||||
|
||||
Args:
|
||||
park_id: Park ID
|
||||
limit: Maximum number of reviews to return
|
||||
|
||||
|
||||
Returns:
|
||||
QuerySet of park reviews
|
||||
"""
|
||||
return ParkReview.objects.filter(
|
||||
park_id=park_id,
|
||||
is_published=True
|
||||
).select_related(
|
||||
'user',
|
||||
'park'
|
||||
).order_by('-created_at')[:limit]
|
||||
return (
|
||||
ParkReview.objects.filter(park_id=park_id, is_published=True)
|
||||
.select_related("user", "park")
|
||||
.order_by("-created_at")[:limit]
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user