mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 23:31: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:
@@ -9,40 +9,59 @@ from .models import Location
|
||||
#
|
||||
# This admin interface is kept for data migration and cleanup purposes only.
|
||||
|
||||
|
||||
@admin.register(Location)
|
||||
class LocationAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'location_type', 'city', 'state', 'country', 'created_at')
|
||||
list_filter = ('location_type', 'country', 'state', 'city')
|
||||
search_fields = ('name', 'street_address', 'city', 'state', 'country')
|
||||
readonly_fields = ('created_at', 'updated_at', 'content_type', 'object_id')
|
||||
|
||||
list_display = (
|
||||
"name",
|
||||
"location_type",
|
||||
"city",
|
||||
"state",
|
||||
"country",
|
||||
"created_at",
|
||||
)
|
||||
list_filter = ("location_type", "country", "state", "city")
|
||||
search_fields = ("name", "street_address", "city", "state", "country")
|
||||
readonly_fields = ("created_at", "updated_at", "content_type", "object_id")
|
||||
|
||||
fieldsets = (
|
||||
('⚠️ DEPRECATED MODEL', {
|
||||
'description': 'This model is deprecated. Use domain-specific location models instead.',
|
||||
'fields': (),
|
||||
}),
|
||||
('Basic Information', {
|
||||
'fields': ('name', 'location_type')
|
||||
}),
|
||||
('Geographic Coordinates', {
|
||||
'fields': ('latitude', 'longitude')
|
||||
}),
|
||||
('Address', {
|
||||
'fields': ('street_address', 'city', 'state', 'country', 'postal_code')
|
||||
}),
|
||||
('Content Type (Read Only)', {
|
||||
'fields': ('content_type', 'object_id'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('created_at', 'updated_at'),
|
||||
'classes': ('collapse',)
|
||||
})
|
||||
(
|
||||
"⚠️ DEPRECATED MODEL",
|
||||
{
|
||||
"description": "This model is deprecated. Use domain-specific location models instead.",
|
||||
"fields": (),
|
||||
},
|
||||
),
|
||||
("Basic Information", {"fields": ("name", "location_type")}),
|
||||
("Geographic Coordinates", {"fields": ("latitude", "longitude")}),
|
||||
(
|
||||
"Address",
|
||||
{
|
||||
"fields": (
|
||||
"street_address",
|
||||
"city",
|
||||
"state",
|
||||
"country",
|
||||
"postal_code",
|
||||
)
|
||||
},
|
||||
),
|
||||
(
|
||||
"Content Type (Read Only)",
|
||||
{
|
||||
"fields": ("content_type", "object_id"),
|
||||
"classes": ("collapse",),
|
||||
},
|
||||
),
|
||||
(
|
||||
"Metadata",
|
||||
{"fields": ("created_at", "updated_at"), "classes": ("collapse",)},
|
||||
),
|
||||
)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).select_related('content_type')
|
||||
|
||||
return super().get_queryset(request).select_related("content_type")
|
||||
|
||||
def has_add_permission(self, request):
|
||||
# Prevent creating new generic Location objects
|
||||
return False
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
import os
|
||||
|
||||
|
||||
class LocationConfig(AppConfig):
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'location'
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "location"
|
||||
|
||||
@@ -13,28 +13,30 @@ from .models import Location
|
||||
# NOTE: All classes below are DEPRECATED
|
||||
# Use domain-specific location forms instead
|
||||
|
||||
|
||||
class LocationForm(forms.ModelForm):
|
||||
"""DEPRECATED: Use domain-specific location forms instead"""
|
||||
|
||||
|
||||
class Meta:
|
||||
model = Location
|
||||
fields = [
|
||||
'name',
|
||||
'location_type',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'street_address',
|
||||
'city',
|
||||
'state',
|
||||
'country',
|
||||
'postal_code',
|
||||
"name",
|
||||
"location_type",
|
||||
"latitude",
|
||||
"longitude",
|
||||
"street_address",
|
||||
"city",
|
||||
"state",
|
||||
"country",
|
||||
"postal_code",
|
||||
]
|
||||
|
||||
|
||||
class LocationSearchForm(forms.Form):
|
||||
"""DEPRECATED: Location search functionality has been moved to parks app"""
|
||||
|
||||
|
||||
query = forms.CharField(
|
||||
max_length=255,
|
||||
required=True,
|
||||
help_text="This form is deprecated. Use location search in the parks app."
|
||||
help_text="This form is deprecated. Use location search in the parks app.",
|
||||
)
|
||||
|
||||
@@ -86,7 +86,10 @@ class Migration(migrations.Migration):
|
||||
"street_address",
|
||||
models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
("city", models.CharField(blank=True, max_length=100, null=True)),
|
||||
(
|
||||
"city",
|
||||
models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
(
|
||||
"state",
|
||||
models.CharField(
|
||||
@@ -96,8 +99,14 @@ class Migration(migrations.Migration):
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
("country", models.CharField(blank=True, max_length=100, null=True)),
|
||||
("postal_code", models.CharField(blank=True, max_length=20, null=True)),
|
||||
(
|
||||
"country",
|
||||
models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
(
|
||||
"postal_code",
|
||||
models.CharField(blank=True, max_length=20, null=True),
|
||||
),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
@@ -115,7 +124,10 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name="LocationEvent",
|
||||
fields=[
|
||||
("pgh_id", models.AutoField(primary_key=True, serialize=False)),
|
||||
(
|
||||
"pgh_id",
|
||||
models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
("pgh_created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("pgh_label", models.TextField(help_text="The event label.")),
|
||||
("id", models.BigIntegerField()),
|
||||
@@ -175,7 +187,10 @@ class Migration(migrations.Migration):
|
||||
"street_address",
|
||||
models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
("city", models.CharField(blank=True, max_length=100, null=True)),
|
||||
(
|
||||
"city",
|
||||
models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
(
|
||||
"state",
|
||||
models.CharField(
|
||||
@@ -185,8 +200,14 @@ class Migration(migrations.Migration):
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
("country", models.CharField(blank=True, max_length=100, null=True)),
|
||||
("postal_code", models.CharField(blank=True, max_length=20, null=True)),
|
||||
(
|
||||
"country",
|
||||
models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
(
|
||||
"postal_code",
|
||||
models.CharField(blank=True, max_length=20, null=True),
|
||||
),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
|
||||
@@ -40,7 +40,10 @@ class Migration(migrations.Migration):
|
||||
constraint=models.CheckConstraint(
|
||||
condition=models.Q(
|
||||
models.Q(("latitude__isnull", True), ("longitude__isnull", True)),
|
||||
models.Q(("latitude__isnull", False), ("longitude__isnull", False)),
|
||||
models.Q(
|
||||
("latitude__isnull", False),
|
||||
("longitude__isnull", False),
|
||||
),
|
||||
_connector="OR",
|
||||
),
|
||||
name="location_coordinates_complete",
|
||||
|
||||
@@ -7,6 +7,7 @@ from django.contrib.gis.geos import Point
|
||||
import pghistory
|
||||
from core.history import TrackedModel
|
||||
|
||||
|
||||
@pghistory.track()
|
||||
class Location(TrackedModel):
|
||||
"""
|
||||
@@ -14,84 +15,93 @@ class Location(TrackedModel):
|
||||
using GenericForeignKey. Stores detailed location information
|
||||
including coordinates and address components.
|
||||
"""
|
||||
|
||||
# Generic relation fields
|
||||
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
||||
object_id = models.PositiveIntegerField()
|
||||
content_object = GenericForeignKey('content_type', 'object_id')
|
||||
content_object = GenericForeignKey("content_type", "object_id")
|
||||
|
||||
# Location name and type
|
||||
name = models.CharField(max_length=255, help_text="Name of the location (e.g. business name, landmark)")
|
||||
location_type = models.CharField(max_length=50, help_text="Type of location (e.g. business, landmark, address)")
|
||||
|
||||
name = models.CharField(
|
||||
max_length=255,
|
||||
help_text="Name of the location (e.g. business name, landmark)",
|
||||
)
|
||||
location_type = models.CharField(
|
||||
max_length=50,
|
||||
help_text="Type of location (e.g. business, landmark, address)",
|
||||
)
|
||||
|
||||
# Geographic coordinates
|
||||
latitude = models.DecimalField(
|
||||
max_digits=9,
|
||||
max_digits=9,
|
||||
decimal_places=6,
|
||||
validators=[
|
||||
MinValueValidator(-90),
|
||||
MaxValueValidator(90)
|
||||
],
|
||||
validators=[MinValueValidator(-90), MaxValueValidator(90)],
|
||||
help_text="Latitude coordinate (legacy field)",
|
||||
null=True,
|
||||
blank=True
|
||||
blank=True,
|
||||
)
|
||||
longitude = models.DecimalField(
|
||||
max_digits=9,
|
||||
max_digits=9,
|
||||
decimal_places=6,
|
||||
validators=[
|
||||
MinValueValidator(-180),
|
||||
MaxValueValidator(180)
|
||||
],
|
||||
validators=[MinValueValidator(-180), MaxValueValidator(180)],
|
||||
help_text="Longitude coordinate (legacy field)",
|
||||
null=True,
|
||||
blank=True
|
||||
blank=True,
|
||||
)
|
||||
|
||||
|
||||
# GeoDjango point field
|
||||
point = gis_models.PointField(
|
||||
srid=4326, # WGS84 coordinate system
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Geographic coordinates as a Point"
|
||||
help_text="Geographic coordinates as a Point",
|
||||
)
|
||||
|
||||
|
||||
# Address components
|
||||
street_address = models.CharField(max_length=255, blank=True, null=True)
|
||||
city = models.CharField(max_length=100, blank=True, null=True)
|
||||
state = models.CharField(max_length=100, blank=True, null=True, help_text="State/Region/Province")
|
||||
state = models.CharField(
|
||||
max_length=100,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="State/Region/Province",
|
||||
)
|
||||
country = models.CharField(max_length=100, blank=True, null=True)
|
||||
postal_code = models.CharField(max_length=20, blank=True, null=True)
|
||||
|
||||
|
||||
# Metadata
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
models.Index(fields=['content_type', 'object_id']),
|
||||
models.Index(fields=['city']),
|
||||
models.Index(fields=['country']),
|
||||
models.Index(fields=["content_type", "object_id"]),
|
||||
models.Index(fields=["city"]),
|
||||
models.Index(fields=["country"]),
|
||||
]
|
||||
ordering = ['name']
|
||||
ordering = ["name"]
|
||||
constraints = [
|
||||
# Business rule: Latitude must be within valid range (-90 to 90)
|
||||
models.CheckConstraint(
|
||||
name="location_latitude_range",
|
||||
check=models.Q(latitude__isnull=True) | (models.Q(latitude__gte=-90) & models.Q(latitude__lte=90)),
|
||||
violation_error_message="Latitude must be between -90 and 90 degrees"
|
||||
check=models.Q(latitude__isnull=True)
|
||||
| (models.Q(latitude__gte=-90) & models.Q(latitude__lte=90)),
|
||||
violation_error_message="Latitude must be between -90 and 90 degrees",
|
||||
),
|
||||
# Business rule: Longitude must be within valid range (-180 to 180)
|
||||
models.CheckConstraint(
|
||||
name="location_longitude_range",
|
||||
check=models.Q(longitude__isnull=True) | (models.Q(longitude__gte=-180) & models.Q(longitude__lte=180)),
|
||||
violation_error_message="Longitude must be between -180 and 180 degrees"
|
||||
check=models.Q(longitude__isnull=True)
|
||||
| (models.Q(longitude__gte=-180) & models.Q(longitude__lte=180)),
|
||||
violation_error_message="Longitude must be between -180 and 180 degrees",
|
||||
),
|
||||
# Business rule: If coordinates are provided, both lat and lng must be present
|
||||
# Business rule: If coordinates are provided, both lat and lng must
|
||||
# be present
|
||||
models.CheckConstraint(
|
||||
name="location_coordinates_complete",
|
||||
check=models.Q(latitude__isnull=True, longitude__isnull=True) |
|
||||
models.Q(latitude__isnull=False, longitude__isnull=False),
|
||||
violation_error_message="Both latitude and longitude must be provided together"
|
||||
check=models.Q(latitude__isnull=True, longitude__isnull=True)
|
||||
| models.Q(latitude__isnull=False, longitude__isnull=False),
|
||||
violation_error_message="Both latitude and longitude must be provided together",
|
||||
),
|
||||
]
|
||||
|
||||
@@ -101,7 +111,9 @@ class Location(TrackedModel):
|
||||
location_parts.append(self.city)
|
||||
if self.country:
|
||||
location_parts.append(self.country)
|
||||
location_str = ", ".join(location_parts) if location_parts else "Unknown location"
|
||||
location_str = (
|
||||
", ".join(location_parts) if location_parts else "Unknown location"
|
||||
)
|
||||
return f"{self.name} ({location_str})"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
@@ -132,7 +144,8 @@ class Location(TrackedModel):
|
||||
def coordinates(self):
|
||||
"""Returns coordinates as a tuple"""
|
||||
if self.point:
|
||||
return (self.point.y, self.point.x) # Returns (latitude, longitude)
|
||||
# Returns (latitude, longitude)
|
||||
return (self.point.y, self.point.x)
|
||||
elif self.latitude is not None and self.longitude is not None:
|
||||
return (float(self.latitude), float(self.longitude))
|
||||
return None
|
||||
@@ -153,7 +166,10 @@ class Location(TrackedModel):
|
||||
"""
|
||||
if not self.point:
|
||||
return Location.objects.none()
|
||||
|
||||
|
||||
return Location.objects.filter(
|
||||
point__distance_lte=(self.point, distance_km * 1000) # Convert km to meters
|
||||
point__distance_lte=(
|
||||
self.point,
|
||||
distance_km * 1000,
|
||||
) # Convert km to meters
|
||||
).exclude(pk=self.pk)
|
||||
|
||||
@@ -1,101 +1,106 @@
|
||||
from django.test import TestCase
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.contrib.gis.geos import Point
|
||||
from django.contrib.gis.measure import D
|
||||
from .models import Location
|
||||
from parks.models.companies import Operator
|
||||
from parks.models import Park
|
||||
from parks.models import Park, Company as Operator
|
||||
|
||||
|
||||
class LocationModelTests(TestCase):
|
||||
def setUp(self):
|
||||
# Create test company
|
||||
self.operator = Operator.objects.create(
|
||||
name='Test Operator',
|
||||
website='http://example.com'
|
||||
name="Test Operator", website="http://example.com"
|
||||
)
|
||||
|
||||
|
||||
# Create test park
|
||||
self.park = Park.objects.create(
|
||||
name='Test Park',
|
||||
owner=self.operator,
|
||||
status='OPERATING'
|
||||
name="Test Park", owner=self.operator, status="OPERATING"
|
||||
)
|
||||
|
||||
|
||||
# Create test location for company
|
||||
self.operator_location = Location.objects.create(
|
||||
content_type=ContentType.objects.get_for_model(Operator),
|
||||
object_id=self.operator.pk,
|
||||
name='Test Operator HQ',
|
||||
location_type='business',
|
||||
street_address='123 Operator St',
|
||||
city='Operator City',
|
||||
state='CS',
|
||||
country='Test Country',
|
||||
postal_code='12345',
|
||||
point=Point(-118.2437, 34.0522) # Los Angeles coordinates
|
||||
name="Test Operator HQ",
|
||||
location_type="business",
|
||||
street_address="123 Operator St",
|
||||
city="Operator City",
|
||||
state="CS",
|
||||
country="Test Country",
|
||||
postal_code="12345",
|
||||
point=Point(-118.2437, 34.0522), # Los Angeles coordinates
|
||||
)
|
||||
|
||||
|
||||
# Create test location for park
|
||||
self.park_location = Location.objects.create(
|
||||
content_type=ContentType.objects.get_for_model(Park),
|
||||
object_id=self.park.pk,
|
||||
name='Test Park Location',
|
||||
location_type='park',
|
||||
street_address='456 Park Ave',
|
||||
city='Park City',
|
||||
state='PC',
|
||||
country='Test Country',
|
||||
postal_code='67890',
|
||||
point=Point(-111.8910, 40.7608) # Park City coordinates
|
||||
name="Test Park Location",
|
||||
location_type="park",
|
||||
street_address="456 Park Ave",
|
||||
city="Park City",
|
||||
state="PC",
|
||||
country="Test Country",
|
||||
postal_code="67890",
|
||||
point=Point(-111.8910, 40.7608), # Park City coordinates
|
||||
)
|
||||
|
||||
def test_location_creation(self):
|
||||
"""Test location instance creation and field values"""
|
||||
# Test company location
|
||||
self.assertEqual(self.operator_location.name, 'Test Operator HQ')
|
||||
self.assertEqual(self.operator_location.location_type, 'business')
|
||||
self.assertEqual(self.operator_location.street_address, '123 Operator St')
|
||||
self.assertEqual(self.operator_location.city, 'Operator City')
|
||||
self.assertEqual(self.operator_location.state, 'CS')
|
||||
self.assertEqual(self.operator_location.country, 'Test Country')
|
||||
self.assertEqual(self.operator_location.postal_code, '12345')
|
||||
self.assertEqual(self.operator_location.name, "Test Operator HQ")
|
||||
self.assertEqual(self.operator_location.location_type, "business")
|
||||
self.assertEqual(self.operator_location.street_address, "123 Operator St")
|
||||
self.assertEqual(self.operator_location.city, "Operator City")
|
||||
self.assertEqual(self.operator_location.state, "CS")
|
||||
self.assertEqual(self.operator_location.country, "Test Country")
|
||||
self.assertEqual(self.operator_location.postal_code, "12345")
|
||||
self.assertIsNotNone(self.operator_location.point)
|
||||
|
||||
|
||||
# Test park location
|
||||
self.assertEqual(self.park_location.name, 'Test Park Location')
|
||||
self.assertEqual(self.park_location.location_type, 'park')
|
||||
self.assertEqual(self.park_location.street_address, '456 Park Ave')
|
||||
self.assertEqual(self.park_location.city, 'Park City')
|
||||
self.assertEqual(self.park_location.state, 'PC')
|
||||
self.assertEqual(self.park_location.country, 'Test Country')
|
||||
self.assertEqual(self.park_location.postal_code, '67890')
|
||||
self.assertEqual(self.park_location.name, "Test Park Location")
|
||||
self.assertEqual(self.park_location.location_type, "park")
|
||||
self.assertEqual(self.park_location.street_address, "456 Park Ave")
|
||||
self.assertEqual(self.park_location.city, "Park City")
|
||||
self.assertEqual(self.park_location.state, "PC")
|
||||
self.assertEqual(self.park_location.country, "Test Country")
|
||||
self.assertEqual(self.park_location.postal_code, "67890")
|
||||
self.assertIsNotNone(self.park_location.point)
|
||||
|
||||
def test_location_str_representation(self):
|
||||
"""Test string representation of location"""
|
||||
expected_company_str = 'Test Operator HQ (Operator City, Test Country)'
|
||||
expected_company_str = "Test Operator HQ (Operator City, Test Country)"
|
||||
self.assertEqual(str(self.operator_location), expected_company_str)
|
||||
|
||||
expected_park_str = 'Test Park Location (Park City, Test Country)'
|
||||
|
||||
expected_park_str = "Test Park Location (Park City, Test Country)"
|
||||
self.assertEqual(str(self.park_location), expected_park_str)
|
||||
|
||||
def test_get_formatted_address(self):
|
||||
"""Test get_formatted_address method"""
|
||||
expected_address = '123 Operator St, Operator City, CS, 12345, Test Country'
|
||||
self.assertEqual(self.operator_location.get_formatted_address(), expected_address)
|
||||
expected_address = "123 Operator St, Operator City, CS, 12345, Test Country"
|
||||
self.assertEqual(
|
||||
self.operator_location.get_formatted_address(), expected_address
|
||||
)
|
||||
|
||||
def test_point_coordinates(self):
|
||||
"""Test point coordinates"""
|
||||
# Test company location point
|
||||
self.assertIsNotNone(self.operator_location.point)
|
||||
self.assertAlmostEqual(self.operator_location.point.y, 34.0522, places=4) # latitude
|
||||
self.assertAlmostEqual(self.operator_location.point.x, -118.2437, places=4) # longitude
|
||||
|
||||
self.assertAlmostEqual(
|
||||
self.operator_location.point.y, 34.0522, places=4
|
||||
) # latitude
|
||||
self.assertAlmostEqual(
|
||||
self.operator_location.point.x, -118.2437, places=4
|
||||
) # longitude
|
||||
|
||||
# Test park location point
|
||||
self.assertIsNotNone(self.park_location.point)
|
||||
self.assertAlmostEqual(self.park_location.point.y, 40.7608, places=4) # latitude
|
||||
self.assertAlmostEqual(self.park_location.point.x, -111.8910, places=4) # longitude
|
||||
self.assertAlmostEqual(
|
||||
self.park_location.point.y, 40.7608, places=4
|
||||
) # latitude
|
||||
self.assertAlmostEqual(
|
||||
self.park_location.point.x, -111.8910, places=4
|
||||
) # longitude
|
||||
|
||||
def test_coordinates_property(self):
|
||||
"""Test coordinates property"""
|
||||
@@ -103,7 +108,7 @@ class LocationModelTests(TestCase):
|
||||
self.assertIsNotNone(company_coords)
|
||||
self.assertAlmostEqual(company_coords[0], 34.0522, places=4) # latitude
|
||||
self.assertAlmostEqual(company_coords[1], -118.2437, places=4) # longitude
|
||||
|
||||
|
||||
park_coords = self.park_location.coordinates
|
||||
self.assertIsNotNone(park_coords)
|
||||
self.assertAlmostEqual(park_coords[0], 40.7608, places=4) # latitude
|
||||
@@ -121,14 +126,14 @@ class LocationModelTests(TestCase):
|
||||
nearby_location = Location.objects.create(
|
||||
content_type=ContentType.objects.get_for_model(Operator),
|
||||
object_id=self.operator.pk,
|
||||
name='Nearby Location',
|
||||
location_type='business',
|
||||
street_address='789 Nearby St',
|
||||
city='Operator City',
|
||||
country='Test Country',
|
||||
point=Point(-118.2438, 34.0523) # Very close to company location
|
||||
name="Nearby Location",
|
||||
location_type="business",
|
||||
street_address="789 Nearby St",
|
||||
city="Operator City",
|
||||
country="Test Country",
|
||||
point=Point(-118.2438, 34.0523), # Very close to company location
|
||||
)
|
||||
|
||||
|
||||
nearby = self.operator_location.nearby_locations(distance_km=1)
|
||||
self.assertEqual(nearby.count(), 1)
|
||||
self.assertEqual(nearby.first(), nearby_location)
|
||||
@@ -138,39 +143,39 @@ class LocationModelTests(TestCase):
|
||||
# Test company location relation
|
||||
company_location = Location.objects.get(
|
||||
content_type=ContentType.objects.get_for_model(Operator),
|
||||
object_id=self.operator.pk
|
||||
object_id=self.operator.pk,
|
||||
)
|
||||
self.assertEqual(company_location, self.operator_location)
|
||||
|
||||
|
||||
# Test park location relation
|
||||
park_location = Location.objects.get(
|
||||
content_type=ContentType.objects.get_for_model(Park),
|
||||
object_id=self.park.pk
|
||||
object_id=self.park.pk,
|
||||
)
|
||||
self.assertEqual(park_location, self.park_location)
|
||||
|
||||
def test_location_updates(self):
|
||||
"""Test location updates"""
|
||||
# Update company location
|
||||
self.operator_location.street_address = 'Updated Address'
|
||||
self.operator_location.city = 'Updated City'
|
||||
self.operator_location.street_address = "Updated Address"
|
||||
self.operator_location.city = "Updated City"
|
||||
self.operator_location.save()
|
||||
|
||||
|
||||
updated_location = Location.objects.get(pk=self.operator_location.pk)
|
||||
self.assertEqual(updated_location.street_address, 'Updated Address')
|
||||
self.assertEqual(updated_location.city, 'Updated City')
|
||||
self.assertEqual(updated_location.street_address, "Updated Address")
|
||||
self.assertEqual(updated_location.city, "Updated City")
|
||||
|
||||
def test_point_sync_with_lat_lon(self):
|
||||
"""Test point synchronization with latitude/longitude fields"""
|
||||
location = Location.objects.create(
|
||||
content_type=ContentType.objects.get_for_model(Operator),
|
||||
object_id=self.operator.pk,
|
||||
name='Test Sync Location',
|
||||
location_type='business',
|
||||
name="Test Sync Location",
|
||||
location_type="business",
|
||||
latitude=34.0522,
|
||||
longitude=-118.2437
|
||||
longitude=-118.2437,
|
||||
)
|
||||
|
||||
|
||||
self.assertIsNotNone(location.point)
|
||||
self.assertAlmostEqual(location.point.y, 34.0522, places=4)
|
||||
self.assertAlmostEqual(location.point.x, -118.2437, places=4)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#
|
||||
# Domain-specific location models are managed through their respective apps:
|
||||
# - Parks app for ParkLocation
|
||||
# - Rides app for RideLocation
|
||||
# - Rides app for RideLocation
|
||||
# - Parks app for CompanyHeadquarters
|
||||
#
|
||||
# This file is kept for reference during migration cleanup only.
|
||||
@@ -14,20 +14,18 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = 'location'
|
||||
app_name = "location"
|
||||
|
||||
# NOTE: All URLs below are DEPRECATED
|
||||
# The location app URLs should not be included in the main URLconf
|
||||
|
||||
urlpatterns = [
|
||||
# DEPRECATED: Use /parks/search/location/ instead
|
||||
path('search/', views.LocationSearchView.as_view(), name='search'),
|
||||
|
||||
# DEPRECATED: Use /parks/search/reverse-geocode/ instead
|
||||
path('reverse-geocode/', views.reverse_geocode, name='reverse_geocode'),
|
||||
|
||||
path("search/", views.LocationSearchView.as_view(), name="search"),
|
||||
# DEPRECATED: Use /parks/search/reverse-geocode/ instead
|
||||
path("reverse-geocode/", views.reverse_geocode, name="reverse_geocode"),
|
||||
# DEPRECATED: Use domain-specific location models instead
|
||||
path('create/', views.LocationCreateView.as_view(), name='create'),
|
||||
path('<int:pk>/update/', views.LocationUpdateView.as_view(), name='update'),
|
||||
path('<int:pk>/delete/', views.LocationDeleteView.as_view(), name='delete'),
|
||||
path("create/", views.LocationCreateView.as_view(), name="create"),
|
||||
path("<int:pk>/update/", views.LocationUpdateView.as_view(), name="update"),
|
||||
path("<int:pk>/delete/", views.LocationDeleteView.as_view(), name="delete"),
|
||||
]
|
||||
|
||||
@@ -1,51 +1,48 @@
|
||||
# DEPRECATED: These views are deprecated and no longer used.
|
||||
#
|
||||
#
|
||||
# Location search functionality has been moved to the parks app:
|
||||
# - parks.views.location_search
|
||||
# - parks.views.reverse_geocode
|
||||
#
|
||||
# Domain-specific location models are now used instead of the generic Location model:
|
||||
# - ParkLocation in parks.models.location
|
||||
# - RideLocation in rides.models.location
|
||||
# - RideLocation in rides.models.location
|
||||
# - CompanyHeadquarters in parks.models.companies
|
||||
#
|
||||
# This file is kept for reference during migration cleanup only.
|
||||
|
||||
import json
|
||||
import requests
|
||||
from django.views.generic import View
|
||||
from django.http import JsonResponse
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.cache import cache
|
||||
from django.conf import settings
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
from django.db.models import Q
|
||||
|
||||
from location.forms import LocationForm
|
||||
from .models import Location
|
||||
|
||||
# NOTE: All classes and functions below are DEPRECATED
|
||||
# Use the equivalent functionality in the parks app instead
|
||||
|
||||
|
||||
class LocationSearchView(View):
|
||||
"""DEPRECATED: Use parks.views.location_search instead"""
|
||||
pass
|
||||
|
||||
|
||||
class LocationCreateView(LoginRequiredMixin, View):
|
||||
"""DEPRECATED: Use domain-specific location models instead"""
|
||||
pass
|
||||
|
||||
|
||||
class LocationUpdateView(LoginRequiredMixin, View):
|
||||
"""DEPRECATED: Use domain-specific location models instead"""
|
||||
pass
|
||||
|
||||
|
||||
class LocationDeleteView(LoginRequiredMixin, View):
|
||||
"""DEPRECATED: Use domain-specific location models instead"""
|
||||
pass
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
def reverse_geocode(request):
|
||||
"""DEPRECATED: Use parks.views.reverse_geocode instead"""
|
||||
return JsonResponse({'error': 'This endpoint is deprecated. Use /parks/search/reverse-geocode/ instead'}, status=410)
|
||||
return JsonResponse(
|
||||
{
|
||||
"error": "This endpoint is deprecated. Use /parks/search/reverse-geocode/ instead"
|
||||
},
|
||||
status=410,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user