mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 09:31:09 -05:00
feat: Implement ride management views and utility functions
- Added functions for checking user privileges, handling photo uploads, preparing form data, and managing form errors. - Created views for listing, creating, updating, and displaying rides, including category-specific views. - Integrated submission handling for ride changes and improved user feedback through messages. - Enhanced data handling with appropriate context and queryset management for better performance and usability.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from typing import Any, Optional, Union, cast
|
||||
from django.db import models
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
@@ -6,32 +7,37 @@ from django.conf import settings
|
||||
import os
|
||||
from .storage import MediaStorage
|
||||
from rides.models import Ride
|
||||
from django.utils import timezone
|
||||
|
||||
def photo_upload_path(instance, filename):
|
||||
def photo_upload_path(instance: models.Model, filename: str) -> str:
|
||||
"""Generate upload path for photos using normalized filenames"""
|
||||
# Get the content type and object
|
||||
content_type = instance.content_type.model
|
||||
obj = instance.content_object
|
||||
photo = cast(Photo, instance)
|
||||
content_type = photo.content_type.model
|
||||
obj = photo.content_object
|
||||
|
||||
if obj is None:
|
||||
raise ValueError("Content object cannot be None")
|
||||
|
||||
# Get object identifier (slug or id)
|
||||
identifier = getattr(obj, 'slug', obj.id)
|
||||
identifier = getattr(obj, 'slug', None)
|
||||
if identifier is None:
|
||||
identifier = obj.pk # Use pk instead of id as it's guaranteed to exist
|
||||
|
||||
# Get the next available number for this object
|
||||
existing_photos = Photo.objects.filter(
|
||||
content_type=instance.content_type,
|
||||
object_id=instance.object_id
|
||||
content_type=photo.content_type,
|
||||
object_id=photo.object_id
|
||||
).count()
|
||||
next_number = existing_photos + 1
|
||||
|
||||
# Create normalized filename
|
||||
ext = os.path.splitext(filename)[1].lower()
|
||||
if not ext:
|
||||
ext = '.jpg' # Default to .jpg if no extension
|
||||
ext = os.path.splitext(filename)[1].lower() or '.jpg' # Default to .jpg if no extension
|
||||
new_filename = f"{identifier}_{next_number}{ext}"
|
||||
|
||||
# If it's a ride photo, store it under the park's directory
|
||||
if content_type == 'ride':
|
||||
ride = Ride.objects.get(id=obj.id)
|
||||
ride = cast(Ride, obj)
|
||||
return f"park/{ride.park.slug}/{identifier}/{new_filename}"
|
||||
|
||||
# For park photos, store directly in park directory
|
||||
@@ -40,7 +46,7 @@ def photo_upload_path(instance, filename):
|
||||
class Photo(models.Model):
|
||||
"""Generic photo model that can be attached to any model"""
|
||||
image = models.ImageField(
|
||||
upload_to=photo_upload_path,
|
||||
upload_to=photo_upload_path, # type: ignore[arg-type]
|
||||
max_length=255,
|
||||
storage=MediaStorage()
|
||||
)
|
||||
@@ -67,13 +73,14 @@ class Photo(models.Model):
|
||||
models.Index(fields=['content_type', 'object_id']),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self) -> str:
|
||||
return f"{self.content_type} - {self.content_object} - {self.caption or 'No caption'}"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
def save(self, *args: Any, **kwargs: Any) -> None:
|
||||
# Set default caption if not provided
|
||||
if not self.caption and self.uploaded_by:
|
||||
self.caption = f"Uploaded by {self.uploaded_by.username} on {self.created_at.strftime('%B %d, %Y at %I:%M %p')}"
|
||||
current_time = timezone.now()
|
||||
self.caption = f"Uploaded by {self.uploaded_by.username} on {current_time.strftime('%B %d, %Y at %I:%M %p')}"
|
||||
|
||||
# If this is marked as primary, unmark other primary photos
|
||||
if self.is_primary:
|
||||
@@ -81,6 +88,6 @@ class Photo(models.Model):
|
||||
content_type=self.content_type,
|
||||
object_id=self.object_id,
|
||||
is_primary=True
|
||||
).exclude(id=self.id).update(is_primary=False)
|
||||
).exclude(pk=self.pk).update(is_primary=False) # Use pk instead of id
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
Reference in New Issue
Block a user