Refactor API structure and add comprehensive user management features

- Restructure API v1 with improved serializers organization
- Add user deletion requests and moderation queue system
- Implement bulk moderation operations and permissions
- Add user profile enhancements with display names and avatars
- Expand ride and park API endpoints with better filtering
- Add manufacturer API with detailed ride relationships
- Improve authentication flows and error handling
- Update frontend documentation and API specifications
This commit is contained in:
pacnpal
2025-08-29 16:03:51 -04:00
parent 7b9f64be72
commit bb7da85516
92 changed files with 19690 additions and 9076 deletions

View File

@@ -113,10 +113,10 @@ class ParkListOutputSerializer(serializers.Serializer):
"thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
"medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
"large": "https://imagedelivery.net/account-hash/def789ghi012/large",
"public": "https://imagedelivery.net/account-hash/def789ghi012/public"
"public": "https://imagedelivery.net/account-hash/def789ghi012/public",
},
"caption": "Beautiful park entrance",
"is_primary": True
"is_primary": True,
}
],
"primary_photo": {
@@ -126,10 +126,10 @@ class ParkListOutputSerializer(serializers.Serializer):
"thumbnail": "https://imagedelivery.net/account-hash/def789ghi012/thumbnail",
"medium": "https://imagedelivery.net/account-hash/def789ghi012/medium",
"large": "https://imagedelivery.net/account-hash/def789ghi012/large",
"public": "https://imagedelivery.net/account-hash/def789ghi012/public"
"public": "https://imagedelivery.net/account-hash/def789ghi012/public",
},
"caption": "Beautiful park entrance"
}
"caption": "Beautiful park entrance",
},
},
)
]
@@ -203,21 +203,28 @@ class ParkDetailOutputSerializer(serializers.Serializer):
"""Get all approved photos for this park."""
from apps.parks.models import ParkPhoto
photos = ParkPhoto.objects.filter(
park=obj,
is_approved=True
).order_by('-is_primary', '-created_at')[:10] # Limit to 10 photos
photos = ParkPhoto.objects.filter(park=obj, is_approved=True).order_by(
"-is_primary", "-created_at"
)[
:10
] # Limit to 10 photos
return [
{
"id": photo.id,
"image_url": photo.image.url if photo.image else None,
"image_variants": {
"thumbnail": f"{photo.image.url}/thumbnail" if photo.image else None,
"medium": f"{photo.image.url}/medium" if photo.image else None,
"large": f"{photo.image.url}/large" if photo.image else None,
"public": f"{photo.image.url}/public" if photo.image else None,
} if photo.image else {},
"image_variants": (
{
"thumbnail": (
f"{photo.image.url}/thumbnail" if photo.image else None
),
"medium": f"{photo.image.url}/medium" if photo.image else None,
"large": f"{photo.image.url}/large" if photo.image else None,
"public": f"{photo.image.url}/public" if photo.image else None,
}
if photo.image
else {}
),
"caption": photo.caption,
"alt_text": photo.alt_text,
"is_primary": photo.is_primary,
@@ -232,9 +239,7 @@ class ParkDetailOutputSerializer(serializers.Serializer):
try:
photo = ParkPhoto.objects.filter(
park=obj,
is_primary=True,
is_approved=True
park=obj, is_primary=True, is_approved=True
).first()
if photo and photo.image:
@@ -275,12 +280,15 @@ class ParkDetailOutputSerializer(serializers.Serializer):
# Fallback to latest approved photo
from apps.parks.models import ParkPhoto
try:
latest_photo = ParkPhoto.objects.filter(
park=obj,
is_approved=True,
image__isnull=False
).order_by('-created_at').first()
latest_photo = (
ParkPhoto.objects.filter(
park=obj, is_approved=True, image__isnull=False
)
.order_by("-created_at")
.first()
)
if latest_photo and latest_photo.image:
return {
@@ -321,12 +329,15 @@ class ParkDetailOutputSerializer(serializers.Serializer):
# Fallback to latest approved photo
from apps.parks.models import ParkPhoto
try:
latest_photo = ParkPhoto.objects.filter(
park=obj,
is_approved=True,
image__isnull=False
).order_by('-created_at').first()
latest_photo = (
ParkPhoto.objects.filter(
park=obj, is_approved=True, image__isnull=False
)
.order_by("-created_at")
.first()
)
if latest_photo and latest_photo.image:
return {
@@ -362,6 +373,7 @@ class ParkImageSettingsInputSerializer(serializers.Serializer):
"""Validate that the banner image belongs to the same park."""
if value is not None:
from apps.parks.models import ParkPhoto
try:
photo = ParkPhoto.objects.get(id=value)
# The park will be validated in the view
@@ -374,6 +386,7 @@ class ParkImageSettingsInputSerializer(serializers.Serializer):
"""Validate that the card image belongs to the same park."""
if value is not None:
from apps.parks.models import ParkPhoto
try:
photo = ParkPhoto.objects.get(id=value)
# The park will be validated in the view