mauflix/source/main/models.py

237 lines
7.4 KiB
Python

import requests
import shutil
import random
import time
import wikipediaapi
from bs4 import BeautifulSoup
from django.conf import settings
from django.db import models
from pathlib import Path
class Gender(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=250)
class Meta:
unique_together = ["name"]
ordering = ["name"]
verbose_name = "Género"
verbose_name_plural = "Generos"
def __str__(self):
return self.name
class Country(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=250, verbose_name="País")
class Meta:
unique_together = ["name"]
ordering = ["name"]
verbose_name = "País"
verbose_name_plural = "Paises"
def __str__(self):
return self.name
class PersonQuerySet(models.QuerySet):
def directors(self):
rows = self.filter(is_director=True).values_list("name", flat=True)
return rows
def actors(self):
rows = self.filter(is_actor=True).values_list("name", flat=True)
return rows
class Person(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField("Nombre", max_length=500)
country = models.ForeignKey(
Country, related_name="country", on_delete=models.PROTECT
)
date_born = models.DateField("Fecha de nacimiento", null=True, blank=True)
is_actor = models.BooleanField("Es Actor", default=False)
is_director = models.BooleanField("Es Director", default=False)
is_woman = models.BooleanField("Es mujer", default=False)
photo = models.ImageField(
"Fotografía", upload_to="%Y/%m/%d/", null=True, blank=True
)
objects = PersonQuerySet.as_manager()
class Meta:
unique_together = ["name"]
ordering = ["name"]
verbose_name = "Persona"
verbose_name_plural = "Personas"
def __str__(self):
return self.name
class MovieQuerySet(models.QuerySet):
def random_pick(self, random_max=6, min_items=20, **kwargs):
all = list(Movie.objects.filter(**kwargs).values())
if len(all) < min_items:
return None
elif len(all) < random_max:
return all
else:
return random.sample(all, random_max)
def top_pick(self, key, top_max=6):
all = list(Movie.objects.order_by(f"-{key}").values())
return all[:top_max]
def top_random_pick(self, key, top_max=6):
all = list(Movie.objects.order_by(f"-{key}").values())
top = []
for movie in all:
if movie[key] == all[0][key]:
top.append(movie)
else:
break
if len(top) > top_max:
return random.sample(top, top_max)
else:
return top
def home_pick(self):
genders = list(Gender.objects.values_list("id", flat=True))
sections = self.home_sections()
for gender in genders:
key = Gender.objects.get(pk=gender).name
picked = self.random_pick(genders=gender)
if picked:
sections["genders"][key] = self.fix_all_data(picked)
return sections
def home_sections(self):
sections = {
"Novedades": self.fix_all_data(self.top_pick("id")),
"Mejor valorados": self.fix_all_data(self.top_random_pick("stars")),
"Más descargados": self.fix_all_data(self.top_pick("count")),
}
sections["genders"] = {}
return sections
def fix_all_data(self, movies):
for movie in movies:
self.fix_data(movie, wikipedia=False)
return movies
def fix_data(self, movie, wikipedia=True):
movie["duration_formatted"] = self.format_duration(movie["duration"])
movie["count_formatted"] = self.format_count(movie["count"])
movie["stars_icons"] = self.format_stars(movie["stars"])
movie["file_name"] = self.fix_path(movie["file_name"])
movie["cartel"] = self.fix_path(movie["cartel"])
if wikipedia:
movie["wiki"] = self.get_wiki(movie)
def fix_path(self, el):
if settings.DEBUG:
return settings.URL_CDN.format(el)
else:
return settings.MEDIA_ROOT / el
def fix_summ(self, raw):
html = BeautifulSoup(raw, "lxml")
for ref in html.find_all("sup", "reference"):
ref.decompose()
clean = list(map(lambda x: str(x), html.body.children))
return " ".join(clean)
def format_stars(self, num):
stars = "" * num
while len(stars) < 5:
stars += ""
return stars
def format_count(self, num):
return "{:,}".format(num)
def format_duration(self, num):
secs = num * 60
return time.strftime("%H:%M", time.gmtime(secs))
def get_wiki(self, movie, again=True):
wiki = self.get_wiki_page(movie["original_name"])
if not wiki:
wiki = self.get_wiki_page(movie["name"])
return wiki
def get_wiki_page(self, title):
try:
lang = settings.LANGUAGE_CODE.split("-")[0]
wiki = wikipediaapi.Wikipedia(
lang, extract_format=wikipediaapi.ExtractFormat.HTML
)
page = wiki.page(title)
if page.exists():
return {
"title": page.title,
"url": page.fullurl,
"summary": self.fix_summ(page.summary),
}
else:
return None
except:
return None
def get_movie(self, id):
movie = Movie.objects.select_related().get(pk=id).__dict__
movie.pop("_state")
self.fix_data(movie)
return movie
def upload_cartel(instance, filename):
first = filename[0].upper()
if first.isdigit():
first = "0"
return f"{first}/{filename}"
class Movie(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField("Nombre", max_length=1000)
original_name = models.CharField(
"Nombre original", max_length=1000, default="", blank=True
)
file_name = models.CharField(
"Nombre archivo", max_length=1000, default="", blank=True
)
year = models.PositiveSmallIntegerField("Año", default=1900)
duration = models.PositiveSmallIntegerField("Duración", default=0)
directors = models.ManyToManyField(
Person, verbose_name="Director", related_name="directors"
)
actors = models.ManyToManyField(Person, related_name="actors", blank=True)
countries = models.ManyToManyField(
Country, related_name="countries", verbose_name="País", blank=True
)
genders = models.ManyToManyField(
Gender, related_name="genders", verbose_name="Género", blank=True
)
cartel = models.ImageField(
"Cartel", upload_to=upload_cartel, null=True, blank=True
)
count = models.PositiveIntegerField("Descargas", default=0)
stars = models.PositiveSmallIntegerField("Estrellas", default=0)
published = models.BooleanField("¿Publicar?", default=True)
is_digital = models.BooleanField("Es digital", default=False)
objects = MovieQuerySet.as_manager()
class Meta:
unique_together = ["name", "original_name"]
ordering = ["name"]
verbose_name = "Película"
verbose_name_plural = "Películas"
def __str__(self):
return self.name