Source code for coalition.content.models.video

"""Video model for managing videos with metadata and attribution."""

from typing import TYPE_CHECKING, Any

from django.core.exceptions import ValidationError
from django.db import models

from coalition.content.html_sanitizer import HTMLSanitizer
from coalition.content.validators import validate_video_file_extension

if TYPE_CHECKING:
    pass


[docs] class Video(models.Model): """ Model for storing videos with metadata and attribution information. This model handles video content across the application, providing proper attribution, licensing, and accessibility information. """ # Video file and basic info
[docs] video = models.FileField( upload_to="videos/", validators=[validate_video_file_extension], help_text="The video file (.mov, .mp4, .webm)", )
[docs] title = models.CharField( max_length=200, help_text="Title or name of the video", )
[docs] alt_text = models.CharField( max_length=200, help_text="Alt text for the video (accessibility)", )
[docs] description = models.TextField( blank=True, help_text="Optional description of the video", )
# Attribution and licensing
[docs] author = models.CharField( max_length=200, blank=True, help_text="Author/creator of the video", )
[docs] license = models.CharField( max_length=100, blank=True, help_text="License of the video (e.g., 'CC BY 2.0', 'All rights reserved')", )
[docs] source_url = models.URLField( blank=True, help_text="Source URL where the video was obtained", )
# Video type categorization
[docs] VIDEO_TYPES = [ ("general", "General Video"), ("hero", "Hero/Background Video"), ("content", "Content Video"), ("campaign", "Campaign Video"), ]
[docs] video_type = models.CharField( max_length=20, choices=VIDEO_TYPES, default="general", help_text="Type/category of the video", )
# Video-specific settings
[docs] autoplay = models.BooleanField( default=True, help_text="Whether the video should autoplay (for hero videos)", )
[docs] loop = models.BooleanField( default=True, help_text="Whether the video should loop continuously", )
[docs] muted = models.BooleanField( default=True, help_text="Whether video should be muted by default (required for autoplay)", )
[docs] show_controls = models.BooleanField( default=False, help_text="Whether to show video playback controls", )
# Metadata
[docs] created_at = models.DateTimeField( auto_now_add=True, help_text="When this video was uploaded", )
[docs] updated_at = models.DateTimeField( auto_now=True, help_text="When this video was last updated", )
[docs] uploaded_by = models.ForeignKey( "auth.User", on_delete=models.SET_NULL, null=True, blank=True, related_name="uploaded_videos", help_text="User who uploaded this video", )
[docs] class Meta:
[docs] db_table = "video"
[docs] verbose_name = "Video"
[docs] verbose_name_plural = "Videos"
[docs] ordering = ["-created_at"]
[docs] def __str__(self) -> str: return self.title
@property
[docs] def video_url(self) -> str: """Return the URL of the uploaded video, or empty string if no video.""" if self.video and hasattr(self.video, "url"): return self.video.url return ""
[docs] def clean(self) -> None: """Validate that autoplay videos are muted.""" if self.autoplay and not self.muted: raise ValidationError( "Autoplay videos must be muted due to browser policies.", )
[docs] def save(self, *args: "Any", **kwargs: "Any") -> None: """Sanitize text fields before saving.""" # Sanitize title and alt_text (should be plain text) if self.title: self.title = HTMLSanitizer.sanitize_plain_text(self.title) if self.alt_text: self.alt_text = HTMLSanitizer.sanitize_plain_text(self.alt_text) if self.author: self.author = HTMLSanitizer.sanitize_plain_text(self.author) if self.license: self.license = HTMLSanitizer.sanitize_plain_text(self.license) # Sanitize description (can have some HTML) if self.description: self.description = HTMLSanitizer.sanitize(self.description) self.full_clean() super().save(*args, **kwargs)