from django.db import models from django.urls import reverse from django.core.validators import MinValueValidator from django.core.exceptions import ValidationError from autoslug import AutoSlugField from website.validators import MaxFileSizeValidator from accounts.models import User from inventory.models import Category, Tag from comments.models import AbstractComment class Suggestion(models.Model): title = models.CharField(verbose_name="titre du jeu", max_length=256, unique=True) slug = AutoSlugField(populate_from="title", unique=True) price = models.DecimalField( max_digits=6, decimal_places=2, verbose_name="prix en euros", validators=[MinValueValidator(0)], ) buy_link = models.URLField(verbose_name="lien vers un site d'achat") nb_player_min = models.PositiveSmallIntegerField( verbose_name="nombre de joueur·se·s minimum" ) nb_player_max = models.PositiveSmallIntegerField( verbose_name="nombre de joueur·se·s maximum" ) player_range_precisions = models.CharField( max_length=256, blank=True, verbose_name="précisions sur le nombre de joueur·se·s", help_text="Pour indiquer une éventuelle contrainte (ex. parité) ou information sur le nombre de joueur·se·s", ) duration_min = models.PositiveSmallIntegerField( verbose_name="durée de partie minimale", help_text="En minutes, telle qu'indiquée par l'éditeur", ) duration_max = models.PositiveSmallIntegerField( verbose_name="durée de partie maximale", help_text="En minutes, telle qu'indiquée par l'éditeur, identique à la durée minimale si laissée vide", blank=True, ) duration_precisions = models.CharField( max_length=256, blank=True, verbose_name="précisions sur la durée de partie", help_text="Pour indiquer des informations complémentaires sur la durée de la partie (ex. évolution en fonction du nombre de joueur·se·s)", ) game_designer = models.CharField( max_length=256, blank=True, verbose_name="game designer" ) illustrator = models.CharField( max_length=256, blank=True, verbose_name="illustrateur·trice" ) editor = models.CharField(max_length=256, blank=True, verbose_name="éditeur") category = models.ForeignKey( Category, on_delete=models.SET_NULL, blank=True, null=True, verbose_name="catégorie", help_text="Idée de catégorie dans laquelle ranger ce jeu", ) tags = models.ManyToManyField( Tag, blank=True, verbose_name="tags qui correspondent à ce jeu", help_text="Vous pouvez en sélectionner plusieurs ou aucun (sur ordinateur Ctrl+Clic change l'état de selection d'un tag)", ) description = models.TextField( blank=True, verbose_name="description", help_text="Peut correspondre à celle de l'éditeur et ne doit pas contenir d'avis personnel", ) image = models.ImageField( upload_to="suggestion_img/", blank=True, verbose_name="image", help_text="Image du jeu de moins de 512 Kio à téléverser (par exemple une photo de sa boite)", validators=[MaxFileSizeValidator(512)], ) upvoting_users = models.ManyToManyField( User, blank=True, related_name="upvoted_suggestions", verbose_name="personnes intéressées", ) class Meta: ordering = ["title"] verbose_name = "suggestion de jeu" verbose_name_plural = "suggestions de jeux" def __str__(self): return self.title def clean(self): if not self.nb_player_min or not self.nb_player_max or not self.duration_min: return if self.nb_player_min > self.nb_player_max: raise ValidationError( { "nb_player_max": "Le nombre de joueur·se·s maximum doit être supérieur au nombre de joueur·se·s minimum" } ) if self.duration_max is None: self.duration_max = self.duration_min if self.duration_min > self.duration_max: raise ValidationError( { "duration_max": "La durée maximale doit être supérieure à la durée minimale" } ) def get_player_range(self): precisions = "" if self.player_range_precisions: precisions = " ({})".format(self.player_range_precisions) if self.nb_player_min != self.nb_player_max: return "{} à {} joueur·se·s{}".format( self.nb_player_min, self.nb_player_max, precisions ) else: return "{} joueur·se·s{}".format(self.nb_player_min, precisions) def get_duration_range(self): precisions = "" if self.duration_precisions: precisions = " ({})".format(self.duration_precisions) elif self.duration_min != self.duration_max: return "{} à {} min{}".format( self.duration_min, self.duration_max, precisions ) else: return "{} min{}".format(self.duration_min, precisions) def get_absolute_url(self): return reverse("suggestions:suggestion", args=(self.slug,)) class SuggestionComment(AbstractComment): commented_object = models.ForeignKey( Suggestion, on_delete=models.CASCADE, related_name="comments", verbose_name="suggestion", ) class Meta: ordering = ["created_on"] verbose_name = "commentaire sur une suggestion" verbose_name_plural = "commentaires sur des suggestions" def get_modification_url(self): return reverse( "suggestions:modify_suggestion_comment", args=(self.commented_object.slug, self.id), )