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_DEBUG.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