#! /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 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 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: