Files
aurora-moments/api/apps/moments/models.py
T
KrisandClaude Sonnet 5 4877e0a779 Initial commit: Aurora Moments self-hosted photo/video sharing platform
Django/DRF + PostgreSQL/Redis/Celery backend with accounts, library,
moments, and notifications apps; React/TypeScript/Vite frontend with
Instagram-style sidebar nav, feed, profiles, nested comment replies,
notifications, and photo/video upload with ffmpeg-generated posters.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-10 10:28:53 -05:00

86 lines
3.3 KiB
Python

from django.conf import settings
from django.db import models
from apps.core.models import Audience, TimeStampedModel
from apps.library.models import LibraryItem
class MomentQuerySet(models.QuerySet):
def visible_to(self, user):
"""FAMILY and CUSTOM audiences intentionally fall back to
owner-only visibility until circles/custom-audience membership
(V1.5) exists — better to under-share than leak content."""
from apps.accounts.models import Follow
following_ids = Follow.objects.filter(
follower=user, status=Follow.Status.ACCEPTED
).values_list("following_id", flat=True)
follower_ids = set(
Follow.objects.filter(
following=user, status=Follow.Status.ACCEPTED
).values_list("follower_id", flat=True)
)
friend_ids = follower_ids & set(following_ids)
return self.filter(
models.Q(owner=user)
| models.Q(audience=Audience.PUBLIC)
| models.Q(audience=Audience.FOLLOWERS, owner_id__in=following_ids)
| models.Q(audience=Audience.FRIENDS, owner_id__in=friend_ids)
).distinct()
class Moment(TimeStampedModel):
"""The social-media object: one or more LibraryItems shared with an
explicit audience. Sharing a Moment never moves or copies the original
file — it just makes the existing library item visible to others."""
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="moments", on_delete=models.CASCADE)
caption = models.TextField(max_length=2200, blank=True)
location = models.CharField(max_length=255, blank=True)
audience = models.CharField(max_length=10, choices=Audience.choices, default=Audience.PUBLIC)
objects = MomentQuerySet.as_manager()
class Meta:
ordering = ["-created_at"]
def __str__(self):
return f"Moment({self.id}) by {self.owner}"
class MomentItem(models.Model):
moment = models.ForeignKey(Moment, related_name="items", on_delete=models.CASCADE)
library_item = models.ForeignKey(LibraryItem, related_name="moment_items", on_delete=models.CASCADE)
order = models.PositiveIntegerField(default=0)
class Meta:
ordering = ["order"]
unique_together = ("moment", "library_item")
class Comment(TimeStampedModel):
moment = models.ForeignKey(Moment, related_name="comments", on_delete=models.CASCADE)
author = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="comments", on_delete=models.CASCADE)
parent = models.ForeignKey("self", related_name="replies", on_delete=models.CASCADE, null=True, blank=True)
body = models.TextField(max_length=1000)
class Meta:
ordering = ["created_at"]
def __str__(self):
return f"{self.author}: {self.body[:40]}"
class Reaction(models.Model):
class ReactionType(models.TextChoices):
LIKE = "like", "Like"
moment = models.ForeignKey(Moment, related_name="reactions", on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="reactions", on_delete=models.CASCADE)
reaction_type = models.CharField(max_length=10, choices=ReactionType.choices, default=ReactionType.LIKE)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ("moment", "user")