mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 05:51:08 -05:00
263 lines
8.1 KiB
Python
263 lines
8.1 KiB
Python
from django.db import models
|
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.conf import settings
|
|
from django.utils import timezone
|
|
from django.apps import apps
|
|
|
|
class EditSubmission(models.Model):
|
|
STATUS_CHOICES = [
|
|
('PENDING', 'Pending'),
|
|
('APPROVED', 'Approved'),
|
|
('REJECTED', 'Rejected'),
|
|
('AUTO_APPROVED', 'Auto Approved'),
|
|
]
|
|
|
|
SUBMISSION_TYPE_CHOICES = [
|
|
('EDIT', 'Edit Existing'),
|
|
('CREATE', 'Create New'),
|
|
]
|
|
|
|
# Who submitted the edit
|
|
user = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.CASCADE,
|
|
related_name='edit_submissions'
|
|
)
|
|
|
|
# What is being edited (Park or Ride)
|
|
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
|
object_id = models.PositiveIntegerField(null=True, blank=True) # Null for new objects
|
|
content_object = GenericForeignKey('content_type', 'object_id')
|
|
|
|
# Type of submission
|
|
submission_type = models.CharField(
|
|
max_length=10,
|
|
choices=SUBMISSION_TYPE_CHOICES,
|
|
default='EDIT'
|
|
)
|
|
|
|
# The actual changes/data
|
|
changes = models.JSONField(
|
|
help_text='JSON representation of the changes or new object data'
|
|
)
|
|
|
|
# Metadata
|
|
reason = models.TextField(
|
|
help_text='Why this edit/addition is needed'
|
|
)
|
|
source = models.TextField(
|
|
blank=True,
|
|
help_text='Source of information (if applicable)'
|
|
)
|
|
status = models.CharField(
|
|
max_length=20,
|
|
choices=STATUS_CHOICES,
|
|
default='PENDING'
|
|
)
|
|
submitted_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
# Review details
|
|
reviewed_by = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name='reviewed_submissions'
|
|
)
|
|
reviewed_at = models.DateTimeField(null=True, blank=True)
|
|
review_notes = models.TextField(
|
|
blank=True,
|
|
help_text='Notes from the moderator about this submission'
|
|
)
|
|
|
|
class Meta:
|
|
ordering = ['-submitted_at']
|
|
indexes = [
|
|
models.Index(fields=['content_type', 'object_id']),
|
|
models.Index(fields=['status']),
|
|
]
|
|
|
|
def __str__(self):
|
|
action = "creation" if self.submission_type == 'CREATE' else "edit"
|
|
target = self.content_object or self.content_type.model_class().__name__
|
|
return f"{action} by {self.user.username} on {target}"
|
|
|
|
def _resolve_foreign_keys(self, data):
|
|
"""Convert foreign key IDs to model instances"""
|
|
model_class = self.content_type.model_class()
|
|
resolved_data = data.copy()
|
|
|
|
for field_name, value in data.items():
|
|
field = model_class._meta.get_field(field_name)
|
|
if isinstance(field, models.ForeignKey) and value is not None:
|
|
related_model = field.related_model
|
|
resolved_data[field_name] = related_model.objects.get(id=value)
|
|
|
|
return resolved_data
|
|
|
|
def approve(self, moderator, notes=''):
|
|
"""Approve the submission and apply the changes"""
|
|
self.status = 'APPROVED'
|
|
self.reviewed_by = moderator
|
|
self.reviewed_at = timezone.now()
|
|
self.review_notes = notes
|
|
|
|
model_class = self.content_type.model_class()
|
|
resolved_data = self._resolve_foreign_keys(self.changes)
|
|
|
|
if self.submission_type == 'CREATE':
|
|
# Create new object
|
|
obj = model_class(**resolved_data)
|
|
obj.save()
|
|
# Update object_id after creation
|
|
self.object_id = obj.id
|
|
else:
|
|
# Apply changes to existing object
|
|
obj = self.content_object
|
|
for field, value in resolved_data.items():
|
|
setattr(obj, field, value)
|
|
obj.save()
|
|
|
|
self.save()
|
|
return obj
|
|
|
|
def reject(self, moderator, notes):
|
|
"""Reject the submission"""
|
|
self.status = 'REJECTED'
|
|
self.reviewed_by = moderator
|
|
self.reviewed_at = timezone.now()
|
|
self.review_notes = notes
|
|
self.save()
|
|
|
|
def auto_approve(self):
|
|
"""Auto-approve the submission (for moderators/admins)"""
|
|
self.status = 'AUTO_APPROVED'
|
|
self.reviewed_by = self.user
|
|
self.reviewed_at = timezone.now()
|
|
|
|
model_class = self.content_type.model_class()
|
|
resolved_data = self._resolve_foreign_keys(self.changes)
|
|
|
|
if self.submission_type == 'CREATE':
|
|
# Create new object
|
|
obj = model_class(**resolved_data)
|
|
obj.save()
|
|
# Update object_id after creation
|
|
self.object_id = obj.id
|
|
else:
|
|
# Apply changes to existing object
|
|
obj = self.content_object
|
|
for field, value in resolved_data.items():
|
|
setattr(obj, field, value)
|
|
obj.save()
|
|
|
|
self.save()
|
|
return obj
|
|
|
|
class PhotoSubmission(models.Model):
|
|
STATUS_CHOICES = [
|
|
('PENDING', 'Pending'),
|
|
('APPROVED', 'Approved'),
|
|
('REJECTED', 'Rejected'),
|
|
('AUTO_APPROVED', 'Auto Approved'),
|
|
]
|
|
|
|
# Who submitted the photo
|
|
user = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.CASCADE,
|
|
related_name='photo_submissions'
|
|
)
|
|
|
|
# What the photo is for (Park or Ride)
|
|
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
|
object_id = models.PositiveIntegerField()
|
|
content_object = GenericForeignKey('content_type', 'object_id')
|
|
|
|
# The photo itself
|
|
photo = models.ImageField(upload_to='submissions/photos/')
|
|
caption = models.CharField(max_length=255, blank=True)
|
|
date_taken = models.DateField(null=True, blank=True)
|
|
|
|
# Metadata
|
|
status = models.CharField(
|
|
max_length=20,
|
|
choices=STATUS_CHOICES,
|
|
default='PENDING'
|
|
)
|
|
submitted_at = models.DateTimeField(auto_now_add=True)
|
|
|
|
# Review details
|
|
reviewed_by = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
on_delete=models.SET_NULL,
|
|
null=True,
|
|
blank=True,
|
|
related_name='reviewed_photos'
|
|
)
|
|
reviewed_at = models.DateTimeField(null=True, blank=True)
|
|
review_notes = models.TextField(
|
|
blank=True,
|
|
help_text='Notes from the moderator about this photo submission'
|
|
)
|
|
|
|
class Meta:
|
|
ordering = ['-submitted_at']
|
|
indexes = [
|
|
models.Index(fields=['content_type', 'object_id']),
|
|
models.Index(fields=['status']),
|
|
]
|
|
|
|
def __str__(self):
|
|
return f"Photo submission by {self.user.username} for {self.content_object}"
|
|
|
|
def approve(self, moderator, notes=''):
|
|
"""Approve the photo submission"""
|
|
from media.models import Photo
|
|
|
|
self.status = 'APPROVED'
|
|
self.reviewed_by = moderator
|
|
self.reviewed_at = timezone.now()
|
|
self.review_notes = notes
|
|
|
|
# Create the approved photo
|
|
Photo.objects.create(
|
|
user=self.user,
|
|
content_type=self.content_type,
|
|
object_id=self.object_id,
|
|
image=self.photo,
|
|
caption=self.caption,
|
|
date_taken=self.date_taken
|
|
)
|
|
|
|
self.save()
|
|
|
|
def reject(self, moderator, notes):
|
|
"""Reject the photo submission"""
|
|
self.status = 'REJECTED'
|
|
self.reviewed_by = moderator
|
|
self.reviewed_at = timezone.now()
|
|
self.review_notes = notes
|
|
self.save()
|
|
|
|
def auto_approve(self):
|
|
"""Auto-approve the photo submission (for moderators/admins)"""
|
|
from media.models import Photo
|
|
|
|
self.status = 'AUTO_APPROVED'
|
|
self.reviewed_by = self.user
|
|
self.reviewed_at = timezone.now()
|
|
|
|
# Create the approved photo
|
|
Photo.objects.create(
|
|
user=self.user,
|
|
content_type=self.content_type,
|
|
object_id=self.object_id,
|
|
image=self.photo,
|
|
caption=self.caption,
|
|
date_taken=self.date_taken
|
|
)
|
|
|
|
self.save()
|