gestiojeux/suggestions/models.py
Guillaume Bertholon 1fea637d7a Use min/max/precisions fields for game duration
There is an data migration for Game items but not for Suggestion items.
It assumes that all duration fields are filled with a single integer or
a range separated by '-' or 'à'.
2021-01-29 12:07:46 +01:00

166 lines
5.8 KiB
Python

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),
)