mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 23:11:09 -05:00
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols. - Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage. - Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
93 lines
3.3 KiB
Python
93 lines
3.3 KiB
Python
from django.db import models
|
|
from django.db.models import functions
|
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
|
from apps.core.history import TrackedModel
|
|
import pghistory
|
|
|
|
|
|
@pghistory.track()
|
|
class ParkReview(TrackedModel):
|
|
# Import managers
|
|
from ..managers import ParkReviewManager
|
|
|
|
objects = ParkReviewManager()
|
|
"""
|
|
A review of a park.
|
|
"""
|
|
park = models.ForeignKey(
|
|
"parks.Park",
|
|
on_delete=models.CASCADE,
|
|
related_name="reviews",
|
|
help_text="Park being reviewed",
|
|
)
|
|
user = models.ForeignKey(
|
|
"accounts.User",
|
|
on_delete=models.CASCADE,
|
|
related_name="park_reviews",
|
|
help_text="User who wrote the review",
|
|
)
|
|
rating = models.PositiveSmallIntegerField(
|
|
validators=[MinValueValidator(1), MaxValueValidator(10)],
|
|
help_text="Rating from 1-10",
|
|
)
|
|
title = models.CharField(max_length=200, help_text="Review title")
|
|
content = models.TextField(help_text="Review content")
|
|
visit_date = models.DateField(help_text="Date the user visited the park")
|
|
|
|
# Metadata
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
updated_at = models.DateTimeField(auto_now=True)
|
|
|
|
# Moderation
|
|
is_published = models.BooleanField(
|
|
default=True, help_text="Whether this review is publicly visible"
|
|
)
|
|
moderation_notes = models.TextField(
|
|
blank=True, help_text="Internal notes from moderators"
|
|
)
|
|
moderated_by = models.ForeignKey(
|
|
"accounts.User",
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name="moderated_park_reviews",
|
|
help_text="Moderator who reviewed this",
|
|
)
|
|
moderated_at = models.DateTimeField(
|
|
null=True, blank=True, help_text="When this review was moderated"
|
|
)
|
|
|
|
class Meta(TrackedModel.Meta):
|
|
verbose_name = "Park Review"
|
|
verbose_name_plural = "Park Reviews"
|
|
ordering = ["-created_at"]
|
|
unique_together = ["park", "user"]
|
|
constraints = [
|
|
# Business rule: Rating must be between 1 and 10 (database level
|
|
# enforcement)
|
|
models.CheckConstraint(
|
|
name="park_review_rating_range",
|
|
check=models.Q(rating__gte=1) & models.Q(rating__lte=10),
|
|
violation_error_message="Rating must be between 1 and 10",
|
|
),
|
|
# Business rule: Visit date cannot be in the future
|
|
models.CheckConstraint(
|
|
name="park_review_visit_date_not_future",
|
|
check=models.Q(visit_date__lte=functions.Now()),
|
|
violation_error_message="Visit date cannot be in the future",
|
|
),
|
|
# Business rule: If moderated, must have moderator and timestamp
|
|
models.CheckConstraint(
|
|
name="park_review_moderation_consistency",
|
|
check=models.Q(moderated_by__isnull=True, moderated_at__isnull=True)
|
|
| models.Q(moderated_by__isnull=False, moderated_at__isnull=False),
|
|
violation_error_message=(
|
|
"Moderated reviews must have both moderator and moderation "
|
|
"timestamp"
|
|
),
|
|
),
|
|
]
|
|
|
|
def __str__(self):
|
|
return f"Review of {self.park.name} by {self.user.username}"
|