474083dd38
Functional loans system for users. No manager interface yet. See: - app "loans" - a few new views/templates in app "inventory"
161 lines
5.3 KiB
Python
161 lines
5.3 KiB
Python
from django.db import models
|
|
from django.urls import reverse
|
|
from django.core.exceptions import ValidationError
|
|
from autoslug import AutoSlugField
|
|
from website.validators import MaxFileSizeValidator
|
|
from comments.models import AbstractComment
|
|
from loans.models import AbstractLoan
|
|
|
|
|
|
class Category(models.Model):
|
|
name = models.CharField(max_length=256, verbose_name="nom", unique=True)
|
|
slug = AutoSlugField(populate_from="name", unique=True)
|
|
|
|
class Meta:
|
|
ordering = ["name"]
|
|
verbose_name = "catégorie"
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def get_absolute_url(self):
|
|
return reverse("inventory:category", args=(self.slug,))
|
|
|
|
|
|
class Tag(models.Model):
|
|
name = models.CharField(max_length=256, verbose_name="nom", unique=True)
|
|
slug = AutoSlugField(populate_from="name", unique=True)
|
|
|
|
class Meta:
|
|
ordering = ["name"]
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
def get_absolute_url(self):
|
|
return reverse("inventory:tag", args=(self.slug,))
|
|
|
|
|
|
class Game(models.Model):
|
|
title = models.CharField(verbose_name="titre du jeu", max_length=256, unique=True)
|
|
slug = AutoSlugField(populate_from="title", unique=True)
|
|
|
|
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 = models.CharField(
|
|
max_length=256,
|
|
blank=True,
|
|
help_text="Affichage personnalisé pour le nombre de joueur·se·s",
|
|
verbose_name="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 = models.CharField(
|
|
max_length=256,
|
|
blank=True,
|
|
help_text="Affichage personnalisé pour la durée de la partie",
|
|
verbose_name="durée de partie",
|
|
)
|
|
|
|
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.RESTRICT, verbose_name="catégorie"
|
|
)
|
|
tags = models.ManyToManyField(Tag, blank=True, verbose_name="tags")
|
|
|
|
description = models.TextField(blank=True, verbose_name="description")
|
|
image = models.ImageField(
|
|
upload_to="game_img/",
|
|
blank=True,
|
|
verbose_name="image",
|
|
help_text="L'image doit peser 512 Kio au maximum",
|
|
validators=[MaxFileSizeValidator(512)],
|
|
)
|
|
|
|
missing_elements = models.TextField(blank=True, verbose_name="pièces manquantes")
|
|
|
|
class Meta:
|
|
ordering = ["title"]
|
|
verbose_name = "jeu"
|
|
verbose_name_plural = "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):
|
|
if self.player_range:
|
|
return self.player_range
|
|
elif self.nb_player_min != self.nb_player_max:
|
|
return "{} à {} joueur·se·s".format(self.nb_player_min, self.nb_player_max)
|
|
else:
|
|
return "{} joueur·se·s".format(self.nb_player_min)
|
|
|
|
def get_duration_range(self):
|
|
if self.duration:
|
|
return self.duration
|
|
elif self.duration_min != self.duration_max:
|
|
return "{} à {} min".format(self.duration_min, self.duration_max)
|
|
else:
|
|
return "{} min".format(self.duration_min)
|
|
|
|
def get_absolute_url(self):
|
|
return reverse("inventory:game", args=(self.slug,))
|
|
|
|
|
|
class GameComment(AbstractComment):
|
|
commented_object = models.ForeignKey(
|
|
Game, on_delete=models.CASCADE, related_name="comments", verbose_name="jeu"
|
|
)
|
|
|
|
class Meta:
|
|
ordering = ["created_on"]
|
|
verbose_name = "commentaire sur un jeu"
|
|
verbose_name_plural = "commentaires sur des jeux"
|
|
|
|
def get_modification_url(self):
|
|
return reverse(
|
|
"inventory:modify_game_comment", args=(self.commented_object.slug, self.id)
|
|
)
|
|
|
|
class GameLoan(AbstractLoan):
|
|
lent_object = models.ForeignKey(
|
|
Game, on_delete=models.CASCADE,
|
|
verbose_name="jeu emprunté"
|
|
)
|