Source code for berhoel.django.media.models

#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""Django models for series application.
"""

# Standard library imports.
import enum
import uuid

# Django library imports.
from django.db import models

from polymorphic.models import PolymorphicModel  # isort: skip

__date__ = "2022/08/13 13:37:17 hoel"
__author__ = "Berthold Höllmann"
__copyright__ = "Copyright © 2015 by Berthold Höllmann"
__credits__ = ["Berthold Höllmann"]
__maintainer__ = "Berthold Höllmann"
__email__ = "berhoel@gmail.com"


# Create your models here.
[docs]class MyDjangoEnum(enum.Enum): "Prepare Enums for Django" @property def do_not_call_in_templates(self) -> bool: "Prevent instances from being called in templates." return True
[docs]class MediaTypes(MyDjangoEnum): "Media types" MEDIA = enum.auto() DVD = enum.auto() BROADCAST = enum.auto() RENTAL_VIDEO = enum.auto() THEATRE_VISIT = enum.auto() STREAMING = enum.auto()
[docs] def __str__(self) -> str: return { self.MEDIA: "Media", self.DVD: "DVD", self.BROADCAST: "Broadcast", self.RENTAL_VIDEO: "RentalVideo", self.THEATRE_VISIT: "TheatreVisit", self.STREAMING: "Streaming", }[self]
[docs]class WatchItemTypes(MyDjangoEnum): "Types for watch items" WATCH_ITEM = enum.auto() FILM = enum.auto() SERIES_EPISODE = enum.auto()
[docs] def __str__(self): return { self.WATCH_ITEM: "WatchItem", self.FILM: "Film", self.SERIES_EPISODE: "SeriesEpisode", }[self]
[docs]class Media(PolymorphicModel): """Base class for mapping diffenrent media.""" _type = MediaTypes.MEDIA id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField("name", max_length=255) family = models.BooleanField("family?", default=False, blank=True) season = models.IntegerField(blank=True, null=True) sub_season = models.IntegerField(blank=True, null=True) class Meta: "Configure Django model class" # pylint: disable=R0903 verbose_name = "media" verbose_name_plural = "media" ordering = ["name", "season", "sub_season"]
[docs] def __str__(self) -> str: return f"{self.name}"
@property def item_type(self) -> enum.Enum: "Return media type" return self._type
[docs]class DVD(Media): """DVD or DVD set.""" _type = MediaTypes.DVD disks = models.IntegerField(null=True) adver_name = models.CharField("adver_name", max_length=255)
[docs] def __str__(self) -> str: # pylint: disable=E1101 res = [ f"{self.name}", f"{self.adver_name}", f"{Purchase.objects.filter(media=self)[0].date}", ] if self.season is not None: if self.sub_season is not None: res.append(f"season {self.season}.{self.sub_season}") else: res.append(f"season {self.season}") return " / ".join(res)
[docs]class Person(models.Model): """General person information.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField(max_length=255) class Meta: "Configure Django model class" # pylint: disable=R0903 ordering = ["name"]
[docs] def __str__(self) -> str: return f"{self.name}"
[docs]class Purchase(models.Model): """Record purchase of media item.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) vendor = models.ForeignKey( Person, on_delete=models.PROTECT, blank=True, null=True, related_name="purchases", related_query_name="purchase", ) price = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) date = models.DateField(blank=True) media = models.ManyToManyField( Media, related_name="purchases", related_query_name="purchase", ) class Meta: "Configure Django model class" # pylint: disable=R0903 ordering = ["-date"]
[docs] def __str__(self) -> str: # pylint: disable=E1101 res = f"{self.date} " if self.vendor is not None: res += f"from {self.vendor.name} for {self.price}€ " else: res += f"for {self.price}€ " return res + f"({' / '.join(i.name for i in self.media.all())})"
[docs]class Sell(models.Model): """Record selling of media item.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) buyer = models.ForeignKey( Person, on_delete=models.PROTECT, blank=True, null=True, related_name="sells", related_query_name="sell", ) price = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True) date = models.DateField(blank=True) dvds = models.ManyToManyField( DVD, related_name="sells", related_query_name="sell", ) class Meta: "Configure Django model class" # pylint: disable=R0903 ordering = ["-date"]
[docs] def __str__(self) -> str: return f"{self.buyer} | {self.date} | {self.price}"
[docs]class WatchItem(PolymorphicModel): """Representing a viewable item.""" _type = WatchItemTypes.WATCH_ITEM id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) medium = models.ForeignKey( Media, on_delete=models.PROTECT, related_name="watch_items", related_query_name="watch_item", ) dvd_index = models.IntegerField(blank=True, null=True) imdb_url = models.URLField(blank=True, null=True) title = models.CharField(max_length=255) desc = models.CharField(max_length=2048, blank=True, null=True)
[docs] def __str__(self): return f"{self.title}"
@property def item_type(self) -> WatchItemTypes: "Return watch item type" return self._type
[docs]class Film(WatchItem): """Watching a film.""" _type = WatchItemTypes.FILM options = models.CharField(max_length=255, blank=True, null=True)
[docs] def __str__(self) -> str: return f"{self.title}"
[docs]class Series(models.Model): """Information of series.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) title = models.CharField(max_length=255) imdb_url = models.URLField(blank=True, null=True) order_no = models.IntegerField() is_active = models.BooleanField(default=False) class Meta: "Configure Django model class" # pylint: disable=R0903 ordering = ["order_no"]
[docs] def __str__(self) -> str: return f"{self.title=} {self.imdb_url=} {self.order_no=} {self.is_active=}"
[docs]class Season(models.Model): """Information on series season as in DVD, broadcast, or streaming.""" series = models.ForeignKey( Series, on_delete=models.PROTECT, related_name="seasons", related_query_name="season", ) season = models.IntegerField() subseason = models.IntegerField(blank=True, null=True)
[docs] def __str__(self) -> str: return f"{self.series=} {self.season=} {self.subseason=}"
[docs]class SeriesEpisode(WatchItem): """Watching an episode of an series.""" _type = WatchItemTypes.SERIES_EPISODE season = models.ForeignKey( Season, on_delete=models.PROTECT, related_name="series_episodes", related_query_name="series_episode", ) episode = models.IntegerField() sub_episode = models.IntegerField(blank=True, null=True)
[docs] def __str__(self) -> str: return f"{self.title}"
[docs]class Broadcast(Media): """Broadcast event of media.""" _type = MediaTypes.BROADCAST broadcast_service = models.ForeignKey( Person, on_delete=models.PROTECT, related_name="broadcasts", related_query_name="broadcast", )
[docs] def __str__(self) -> str: res = [f"{self.name}", f"{self.broadcast_service.name}"] if self.season is not None: if self.sub_season is not None: res.append(f"season {self.season}.{self.sub_season}") else: res.append(f"season {self.season}") return " / ".join(res)
[docs]class RentalVideo(Media): """Seen media in cinema.""" _type = MediaTypes.RENTAL_VIDEO company = models.ForeignKey( Person, on_delete=models.PROTECT, related_name="rental_videos", related_query_name="rental_video", ) price = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
[docs] def __str__(self) -> str: res = [f"{self.name}", f"{self.company.name}"] if self.season is not None: if self.sub_season is not None: res.append(f"season {self.season}.{self.sub_season}") else: res.append(f"season {self.season}") return " / ".join(res)
[docs]class TheatreVisit(Media): """Seen media in cinema.""" _type = MediaTypes.THEATRE_VISIT theatre = models.ForeignKey( Person, on_delete=models.PROTECT, related_name="theatre_visits", related_query_name="theatre_visit", ) price = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
[docs] def __str__(self) -> str: return f"{self.name} / {self.theatre.name}"
[docs]class SubscriptionPayment(models.Model): """Payment for subscription service.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) start = models.DateField() end = models.DateField() amount = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
[docs]class Subscription(models.Model): """Streaming subscription.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) start = models.DateField() end = models.DateField() payments = models.ManyToManyField( SubscriptionPayment, related_name="subscriptions", related_query_name="subscription", )
[docs]class Streaming(Media): """Media streamed via streaming service.""" _type = MediaTypes.STREAMING streaming_service = models.ForeignKey( Person, on_delete=models.PROTECT, related_name="streamings", related_query_name="streaming", ) subscription = models.ManyToManyField( Subscription, related_name="streamings", related_query_name="streaming", )
[docs] def __str__(self) -> str: res = [f"{self.name}", f"{self.streaming_service.name}"] if self.season is not None: if self.sub_season is not None: res.append(f"season {self.season}.{self.sub_season}") else: res.append(f"season {self.season}") return " / ".join(res)
[docs]class Seen(models.Model): """Represents a viewing event.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) date = models.DateField() watch_item = models.ForeignKey( WatchItem, on_delete=models.PROTECT, related_name="seens", related_query_name="seen", ) class Meta: "Configure Django model class" # pylint: disable=R0903 ordering = ["-date"] WatchItemTypes_ = WatchItemTypes
[docs] def __str__(self) -> str: # pylint: disable=E1101 return f"{self.date}: {self.watch_item.title}"
@property def media_type(self) -> str: # pylint: disable=E1101 "return mediat type as string" return f"{self.watch_item.medium.item_type}"
# Local Variables: # mode: python # compile-command: "python ../../../setup.py test" # time-stamp-pattern: "30/__date__ = \"%:y/%02m/%02d %02H:%02M:%02S %u\"" # End: