mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-21 09:31:09 -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:
@@ -4,52 +4,53 @@ Separates Input and Output serializers for clear boundaries.
|
||||
"""
|
||||
|
||||
from rest_framework import serializers
|
||||
from django.contrib.gis.geos import Point
|
||||
from ..models import Park, ParkArea, Company, ParkReview
|
||||
from ..models import Park
|
||||
|
||||
|
||||
class ParkLocationOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for park location data."""
|
||||
|
||||
latitude = serializers.SerializerMethodField()
|
||||
longitude = serializers.SerializerMethodField()
|
||||
city = serializers.SerializerMethodField()
|
||||
state = serializers.SerializerMethodField()
|
||||
country = serializers.SerializerMethodField()
|
||||
formatted_address = serializers.SerializerMethodField()
|
||||
|
||||
|
||||
def get_latitude(self, obj):
|
||||
if hasattr(obj, 'location') and obj.location:
|
||||
if hasattr(obj, "location") and obj.location:
|
||||
return obj.location.latitude
|
||||
return None
|
||||
|
||||
|
||||
def get_longitude(self, obj):
|
||||
if hasattr(obj, 'location') and obj.location:
|
||||
if hasattr(obj, "location") and obj.location:
|
||||
return obj.location.longitude
|
||||
return None
|
||||
|
||||
|
||||
def get_city(self, obj):
|
||||
if hasattr(obj, 'location') and obj.location:
|
||||
if hasattr(obj, "location") and obj.location:
|
||||
return obj.location.city
|
||||
return None
|
||||
|
||||
|
||||
def get_state(self, obj):
|
||||
if hasattr(obj, 'location') and obj.location:
|
||||
if hasattr(obj, "location") and obj.location:
|
||||
return obj.location.state
|
||||
return None
|
||||
|
||||
|
||||
def get_country(self, obj):
|
||||
if hasattr(obj, 'location') and obj.location:
|
||||
if hasattr(obj, "location") and obj.location:
|
||||
return obj.location.country
|
||||
return None
|
||||
|
||||
|
||||
def get_formatted_address(self, obj):
|
||||
if hasattr(obj, 'location') and obj.location:
|
||||
if hasattr(obj, "location") and obj.location:
|
||||
return obj.location.formatted_address
|
||||
return ""
|
||||
|
||||
|
||||
class CompanyOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for company data."""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
@@ -58,6 +59,7 @@ class CompanyOutputSerializer(serializers.Serializer):
|
||||
|
||||
class ParkAreaOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for park area data."""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
@@ -66,23 +68,26 @@ class ParkAreaOutputSerializer(serializers.Serializer):
|
||||
|
||||
class ParkListOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for park list view."""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
status = serializers.CharField()
|
||||
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)
|
||||
|
||||
|
||||
# Location (simplified for list view)
|
||||
location = ParkLocationOutputSerializer(allow_null=True)
|
||||
|
||||
|
||||
# Operator info
|
||||
operator = CompanyOutputSerializer()
|
||||
|
||||
|
||||
# Metadata
|
||||
created_at = serializers.DateTimeField()
|
||||
updated_at = serializers.DateTimeField()
|
||||
@@ -90,34 +95,39 @@ class ParkListOutputSerializer(serializers.Serializer):
|
||||
|
||||
class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for park detail view."""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
status = serializers.CharField()
|
||||
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)
|
||||
|
||||
|
||||
# Location (full details)
|
||||
location = ParkLocationOutputSerializer(allow_null=True)
|
||||
|
||||
|
||||
# Companies
|
||||
operator = CompanyOutputSerializer()
|
||||
property_owner = CompanyOutputSerializer(allow_null=True)
|
||||
|
||||
|
||||
# Areas
|
||||
areas = ParkAreaOutputSerializer(many=True)
|
||||
|
||||
|
||||
# Metadata
|
||||
created_at = serializers.DateTimeField()
|
||||
updated_at = serializers.DateTimeField()
|
||||
@@ -125,171 +135,170 @@ class ParkDetailOutputSerializer(serializers.Serializer):
|
||||
|
||||
class ParkCreateInputSerializer(serializers.Serializer):
|
||||
"""Input serializer for creating parks."""
|
||||
|
||||
name = serializers.CharField(max_length=255)
|
||||
description = serializers.CharField(allow_blank=True, default="")
|
||||
status = serializers.ChoiceField(
|
||||
choices=Park.STATUS_CHOICES,
|
||||
default="OPERATING"
|
||||
)
|
||||
|
||||
status = serializers.ChoiceField(choices=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)
|
||||
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
|
||||
max_digits=10, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
website = serializers.URLField(required=False, allow_blank=True)
|
||||
|
||||
|
||||
# Required operator
|
||||
operator_id = serializers.IntegerField()
|
||||
|
||||
|
||||
# Optional property owner
|
||||
property_owner_id = serializers.IntegerField(required=False, allow_null=True)
|
||||
|
||||
|
||||
def validate(self, data):
|
||||
"""Cross-field validation."""
|
||||
opening_date = data.get('opening_date')
|
||||
closing_date = data.get('closing_date')
|
||||
|
||||
opening_date = data.get("opening_date")
|
||||
closing_date = data.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class ParkUpdateInputSerializer(serializers.Serializer):
|
||||
"""Input serializer for updating parks."""
|
||||
|
||||
name = serializers.CharField(max_length=255, required=False)
|
||||
description = serializers.CharField(allow_blank=True, required=False)
|
||||
status = serializers.ChoiceField(
|
||||
choices=Park.STATUS_CHOICES,
|
||||
required=False
|
||||
)
|
||||
|
||||
status = serializers.ChoiceField(choices=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)
|
||||
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
|
||||
max_digits=10, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
website = serializers.URLField(required=False, allow_blank=True)
|
||||
|
||||
|
||||
# Companies
|
||||
operator_id = serializers.IntegerField(required=False)
|
||||
property_owner_id = serializers.IntegerField(required=False, allow_null=True)
|
||||
|
||||
|
||||
def validate(self, data):
|
||||
"""Cross-field validation."""
|
||||
opening_date = data.get('opening_date')
|
||||
closing_date = data.get('closing_date')
|
||||
|
||||
opening_date = data.get("opening_date")
|
||||
closing_date = data.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class ParkFilterInputSerializer(serializers.Serializer):
|
||||
"""Input serializer for park filtering and search."""
|
||||
|
||||
# Search
|
||||
search = serializers.CharField(required=False, allow_blank=True)
|
||||
|
||||
|
||||
# Status filter
|
||||
status = serializers.MultipleChoiceField(
|
||||
choices=Park.STATUS_CHOICES,
|
||||
required=False
|
||||
choices=Park.STATUS_CHOICES, required=False
|
||||
)
|
||||
|
||||
|
||||
# Location filters
|
||||
country = serializers.CharField(required=False, allow_blank=True)
|
||||
state = serializers.CharField(required=False, allow_blank=True)
|
||||
city = serializers.CharField(required=False, allow_blank=True)
|
||||
|
||||
|
||||
# Rating filter
|
||||
min_rating = serializers.DecimalField(
|
||||
max_digits=3,
|
||||
decimal_places=2,
|
||||
max_digits=3,
|
||||
decimal_places=2,
|
||||
required=False,
|
||||
min_value=1,
|
||||
max_value=10
|
||||
max_value=10,
|
||||
)
|
||||
|
||||
|
||||
# Size filter
|
||||
min_size_acres = serializers.DecimalField(
|
||||
max_digits=10,
|
||||
decimal_places=2,
|
||||
required=False,
|
||||
min_value=0
|
||||
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
|
||||
max_digits=10, decimal_places=2, required=False, min_value=0
|
||||
)
|
||||
|
||||
|
||||
# Company filters
|
||||
operator_id = serializers.IntegerField(required=False)
|
||||
property_owner_id = serializers.IntegerField(required=False)
|
||||
|
||||
|
||||
# Ordering
|
||||
ordering = serializers.ChoiceField(
|
||||
choices=[
|
||||
'name', '-name',
|
||||
'opening_date', '-opening_date',
|
||||
'average_rating', '-average_rating',
|
||||
'coaster_count', '-coaster_count',
|
||||
'created_at', '-created_at'
|
||||
"name",
|
||||
"-name",
|
||||
"opening_date",
|
||||
"-opening_date",
|
||||
"average_rating",
|
||||
"-average_rating",
|
||||
"coaster_count",
|
||||
"-coaster_count",
|
||||
"created_at",
|
||||
"-created_at",
|
||||
],
|
||||
required=False,
|
||||
default='name'
|
||||
default="name",
|
||||
)
|
||||
|
||||
|
||||
class ParkReviewOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for park reviews."""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
rating = serializers.IntegerField()
|
||||
title = serializers.CharField()
|
||||
content = serializers.CharField()
|
||||
visit_date = serializers.DateField()
|
||||
created_at = serializers.DateTimeField()
|
||||
|
||||
|
||||
# User info (limited for privacy)
|
||||
user = serializers.SerializerMethodField()
|
||||
|
||||
|
||||
def get_user(self, obj):
|
||||
return {
|
||||
'username': obj.user.username,
|
||||
'display_name': obj.user.get_full_name() or obj.user.username
|
||||
"username": obj.user.username,
|
||||
"display_name": obj.user.get_full_name() or obj.user.username,
|
||||
}
|
||||
|
||||
|
||||
class ParkStatsOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for park statistics."""
|
||||
|
||||
total_parks = serializers.IntegerField()
|
||||
operating_parks = serializers.IntegerField()
|
||||
closed_parks = serializers.IntegerField()
|
||||
under_construction = serializers.IntegerField()
|
||||
|
||||
|
||||
# Averages
|
||||
average_rating = serializers.DecimalField(max_digits=3, decimal_places=2, allow_null=True)
|
||||
average_coaster_count = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True)
|
||||
|
||||
average_rating = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=2, allow_null=True
|
||||
)
|
||||
average_coaster_count = serializers.DecimalField(
|
||||
max_digits=5, decimal_places=2, allow_null=True
|
||||
)
|
||||
|
||||
# Top countries
|
||||
top_countries = serializers.ListField(child=serializers.DictField())
|
||||
|
||||
|
||||
# Recently added
|
||||
recently_added_count = serializers.IntegerField()
|
||||
|
||||
Reference in New Issue
Block a user