mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-01-01 22:07:03 -05:00
feat: Implement initial schema and add various API, service, and management command enhancements across the application.
This commit is contained in:
@@ -52,16 +52,11 @@ class ParkListOutputSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
status = RichChoiceFieldSerializer(
|
||||
choice_group="statuses",
|
||||
domain="parks"
|
||||
)
|
||||
status = RichChoiceFieldSerializer(choice_group="statuses", domain="parks")
|
||||
description = serializers.CharField()
|
||||
|
||||
# Statistics
|
||||
average_rating = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=2, allow_null=True
|
||||
)
|
||||
average_rating = serializers.DecimalField(max_digits=3, decimal_places=2, allow_null=True)
|
||||
coaster_count = serializers.IntegerField(allow_null=True)
|
||||
ride_count = serializers.IntegerField(allow_null=True)
|
||||
|
||||
@@ -145,25 +140,18 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
status = RichChoiceFieldSerializer(
|
||||
choice_group="statuses",
|
||||
domain="parks"
|
||||
)
|
||||
status = RichChoiceFieldSerializer(choice_group="statuses", domain="parks")
|
||||
description = serializers.CharField()
|
||||
|
||||
# Details
|
||||
opening_date = serializers.DateField(allow_null=True)
|
||||
closing_date = serializers.DateField(allow_null=True)
|
||||
operating_season = serializers.CharField()
|
||||
size_acres = serializers.DecimalField(
|
||||
max_digits=10, decimal_places=2, allow_null=True
|
||||
)
|
||||
size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, allow_null=True)
|
||||
website = serializers.URLField()
|
||||
|
||||
# Statistics
|
||||
average_rating = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=2, allow_null=True
|
||||
)
|
||||
average_rating = serializers.DecimalField(max_digits=3, decimal_places=2, allow_null=True)
|
||||
coaster_count = serializers.IntegerField(allow_null=True)
|
||||
ride_count = serializers.IntegerField(allow_null=True)
|
||||
|
||||
@@ -211,9 +199,7 @@ 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"
|
||||
)[
|
||||
photos = ParkPhoto.objects.filter(park=obj, is_approved=True).order_by("-is_primary", "-created_at")[
|
||||
:10
|
||||
] # Limit to 10 photos
|
||||
|
||||
@@ -228,7 +214,9 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
"public": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "public"),
|
||||
},
|
||||
"friendly_urls": {
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "thumbnail"),
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, photo.caption, photo.pk, "thumbnail"
|
||||
),
|
||||
"medium": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "medium"),
|
||||
"large": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "large"),
|
||||
"public": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "public"),
|
||||
@@ -246,9 +234,7 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
from apps.parks.models import ParkPhoto
|
||||
|
||||
try:
|
||||
photo = ParkPhoto.objects.filter(
|
||||
park=obj, is_primary=True, is_approved=True
|
||||
).first()
|
||||
photo = ParkPhoto.objects.filter(park=obj, is_primary=True, is_approved=True).first()
|
||||
|
||||
if photo and photo.image:
|
||||
return {
|
||||
@@ -261,7 +247,9 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
"public": MediaURLService.get_cloudflare_url_with_fallback(photo.image, "public"),
|
||||
},
|
||||
"friendly_urls": {
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "thumbnail"),
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, photo.caption, photo.pk, "thumbnail"
|
||||
),
|
||||
"medium": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "medium"),
|
||||
"large": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "large"),
|
||||
"public": MediaURLService.generate_park_photo_url(obj.slug, photo.caption, photo.pk, "public"),
|
||||
@@ -289,10 +277,18 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
"public": MediaURLService.get_cloudflare_url_with_fallback(obj.banner_image.image, "public"),
|
||||
},
|
||||
"friendly_urls": {
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(obj.slug, obj.banner_image.caption, obj.banner_image.pk, "thumbnail"),
|
||||
"medium": MediaURLService.generate_park_photo_url(obj.slug, obj.banner_image.caption, obj.banner_image.pk, "medium"),
|
||||
"large": MediaURLService.generate_park_photo_url(obj.slug, obj.banner_image.caption, obj.banner_image.pk, "large"),
|
||||
"public": MediaURLService.generate_park_photo_url(obj.slug, obj.banner_image.caption, obj.banner_image.pk, "public"),
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.banner_image.caption, obj.banner_image.pk, "thumbnail"
|
||||
),
|
||||
"medium": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.banner_image.caption, obj.banner_image.pk, "medium"
|
||||
),
|
||||
"large": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.banner_image.caption, obj.banner_image.pk, "large"
|
||||
),
|
||||
"public": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.banner_image.caption, obj.banner_image.pk, "public"
|
||||
),
|
||||
},
|
||||
"caption": obj.banner_image.caption,
|
||||
"alt_text": obj.banner_image.alt_text,
|
||||
@@ -303,9 +299,7 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
|
||||
try:
|
||||
latest_photo = (
|
||||
ParkPhoto.objects.filter(
|
||||
park=obj, is_approved=True, image__isnull=False
|
||||
)
|
||||
ParkPhoto.objects.filter(park=obj, is_approved=True, image__isnull=False)
|
||||
.order_by("-created_at")
|
||||
.first()
|
||||
)
|
||||
@@ -321,10 +315,18 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
"public": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "public"),
|
||||
},
|
||||
"friendly_urls": {
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "thumbnail"),
|
||||
"medium": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "medium"),
|
||||
"large": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "large"),
|
||||
"public": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "public"),
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "thumbnail"
|
||||
),
|
||||
"medium": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "medium"
|
||||
),
|
||||
"large": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "large"
|
||||
),
|
||||
"public": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "public"
|
||||
),
|
||||
},
|
||||
"caption": latest_photo.caption,
|
||||
"alt_text": latest_photo.alt_text,
|
||||
@@ -350,10 +352,18 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
"public": MediaURLService.get_cloudflare_url_with_fallback(obj.card_image.image, "public"),
|
||||
},
|
||||
"friendly_urls": {
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(obj.slug, obj.card_image.caption, obj.card_image.pk, "thumbnail"),
|
||||
"medium": MediaURLService.generate_park_photo_url(obj.slug, obj.card_image.caption, obj.card_image.pk, "medium"),
|
||||
"large": MediaURLService.generate_park_photo_url(obj.slug, obj.card_image.caption, obj.card_image.pk, "large"),
|
||||
"public": MediaURLService.generate_park_photo_url(obj.slug, obj.card_image.caption, obj.card_image.pk, "public"),
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.card_image.caption, obj.card_image.pk, "thumbnail"
|
||||
),
|
||||
"medium": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.card_image.caption, obj.card_image.pk, "medium"
|
||||
),
|
||||
"large": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.card_image.caption, obj.card_image.pk, "large"
|
||||
),
|
||||
"public": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, obj.card_image.caption, obj.card_image.pk, "public"
|
||||
),
|
||||
},
|
||||
"caption": obj.card_image.caption,
|
||||
"alt_text": obj.card_image.alt_text,
|
||||
@@ -364,9 +374,7 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
|
||||
try:
|
||||
latest_photo = (
|
||||
ParkPhoto.objects.filter(
|
||||
park=obj, is_approved=True, image__isnull=False
|
||||
)
|
||||
ParkPhoto.objects.filter(park=obj, is_approved=True, image__isnull=False)
|
||||
.order_by("-created_at")
|
||||
.first()
|
||||
)
|
||||
@@ -382,10 +390,18 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
"public": MediaURLService.get_cloudflare_url_with_fallback(latest_photo.image, "public"),
|
||||
},
|
||||
"friendly_urls": {
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "thumbnail"),
|
||||
"medium": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "medium"),
|
||||
"large": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "large"),
|
||||
"public": MediaURLService.generate_park_photo_url(obj.slug, latest_photo.caption, latest_photo.pk, "public"),
|
||||
"thumbnail": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "thumbnail"
|
||||
),
|
||||
"medium": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "medium"
|
||||
),
|
||||
"large": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "large"
|
||||
),
|
||||
"public": MediaURLService.generate_park_photo_url(
|
||||
obj.slug, latest_photo.caption, latest_photo.pk, "public"
|
||||
),
|
||||
},
|
||||
"caption": latest_photo.caption,
|
||||
"alt_text": latest_photo.alt_text,
|
||||
@@ -417,7 +433,7 @@ class ParkImageSettingsInputSerializer(serializers.Serializer):
|
||||
# The park will be validated in the view
|
||||
return value
|
||||
except ParkPhoto.DoesNotExist:
|
||||
raise serializers.ValidationError("Photo not found")
|
||||
raise serializers.ValidationError("Photo not found") from None
|
||||
return value
|
||||
|
||||
def validate_card_image_id(self, value):
|
||||
@@ -430,7 +446,7 @@ class ParkImageSettingsInputSerializer(serializers.Serializer):
|
||||
# The park will be validated in the view
|
||||
return value
|
||||
except ParkPhoto.DoesNotExist:
|
||||
raise serializers.ValidationError("Photo not found")
|
||||
raise serializers.ValidationError("Photo not found") from None
|
||||
return value
|
||||
|
||||
|
||||
@@ -439,19 +455,13 @@ class ParkCreateInputSerializer(serializers.Serializer):
|
||||
|
||||
name = serializers.CharField(max_length=255)
|
||||
description = serializers.CharField(allow_blank=True, default="")
|
||||
status = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_park_status_choices(), default="OPERATING"
|
||||
)
|
||||
status = serializers.ChoiceField(choices=ModelChoices.get_park_status_choices(), default="OPERATING")
|
||||
|
||||
# Optional details
|
||||
opening_date = serializers.DateField(required=False, allow_null=True)
|
||||
closing_date = serializers.DateField(required=False, allow_null=True)
|
||||
operating_season = serializers.CharField(
|
||||
max_length=255, required=False, allow_blank=True
|
||||
)
|
||||
size_acres = serializers.DecimalField(
|
||||
max_digits=10, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
operating_season = serializers.CharField(max_length=255, required=False, allow_blank=True)
|
||||
size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, allow_null=True)
|
||||
website = serializers.URLField(required=False, allow_blank=True)
|
||||
|
||||
# Required operator
|
||||
@@ -466,9 +476,7 @@ class ParkCreateInputSerializer(serializers.Serializer):
|
||||
closing_date = attrs.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
raise serializers.ValidationError("Closing date cannot be before opening date")
|
||||
|
||||
return attrs
|
||||
|
||||
@@ -478,19 +486,13 @@ class ParkUpdateInputSerializer(serializers.Serializer):
|
||||
|
||||
name = serializers.CharField(max_length=255, required=False)
|
||||
description = serializers.CharField(allow_blank=True, required=False)
|
||||
status = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_park_status_choices(), required=False
|
||||
)
|
||||
status = serializers.ChoiceField(choices=ModelChoices.get_park_status_choices(), required=False)
|
||||
|
||||
# Optional details
|
||||
opening_date = serializers.DateField(required=False, allow_null=True)
|
||||
closing_date = serializers.DateField(required=False, allow_null=True)
|
||||
operating_season = serializers.CharField(
|
||||
max_length=255, required=False, allow_blank=True
|
||||
)
|
||||
size_acres = serializers.DecimalField(
|
||||
max_digits=10, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
operating_season = serializers.CharField(max_length=255, required=False, allow_blank=True)
|
||||
size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, allow_null=True)
|
||||
website = serializers.URLField(required=False, allow_blank=True)
|
||||
|
||||
# Companies
|
||||
@@ -503,9 +505,7 @@ class ParkUpdateInputSerializer(serializers.Serializer):
|
||||
closing_date = attrs.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
raise serializers.ValidationError("Closing date cannot be before opening date")
|
||||
|
||||
return attrs
|
||||
|
||||
@@ -537,12 +537,8 @@ class ParkFilterInputSerializer(serializers.Serializer):
|
||||
)
|
||||
|
||||
# Size filter
|
||||
min_size_acres = serializers.DecimalField(
|
||||
max_digits=10, decimal_places=2, required=False, min_value=0
|
||||
)
|
||||
max_size_acres = serializers.DecimalField(
|
||||
max_digits=10, decimal_places=2, required=False, min_value=0
|
||||
)
|
||||
min_size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, min_value=0)
|
||||
max_size_acres = serializers.DecimalField(max_digits=10, decimal_places=2, required=False, min_value=0)
|
||||
|
||||
# Company filters
|
||||
operator_id = serializers.IntegerField(required=False)
|
||||
@@ -625,9 +621,7 @@ class ParkAreaCreateInputSerializer(serializers.Serializer):
|
||||
closing_date = attrs.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
raise serializers.ValidationError("Closing date cannot be before opening date")
|
||||
|
||||
return attrs
|
||||
|
||||
@@ -646,9 +640,7 @@ class ParkAreaUpdateInputSerializer(serializers.Serializer):
|
||||
closing_date = attrs.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
raise serializers.ValidationError("Closing date cannot be before opening date")
|
||||
|
||||
return attrs
|
||||
|
||||
|
||||
Reference in New Issue
Block a user