Création d'une formule de promotion (dur dur)
Hello la Team Docstring,
Derniere ligne droit sur mon projet d'école et il y a une derniere chose que je n'arrive pas à mettre en place. J'ai essayé sous plusieurs formes mais sans succès. La dernière fonction que j'essaie de mettre en place est de calculer le prix final d'un produit mis en promotion. Dans mon backend j'ai la case promo ou l'on rentre le pourcentage de la promotion et je n'arrive pas faire en sorte d'afficher le resultat de la promotion coté front. J'ai essayé de plusieurs manière.
La premiere chose que j'ai essayé c'est directement dans le gabarit avec une formule comme celle ci :
Voici ma class dans models :
class ProductMeat(models.Model):
title = models.CharField(max_length=38, unique=True, verbose_name="Viande")
slug = models.SlugField(max_length=38, unique=True, blank=True)
price = models.FloatField(default=0.0, verbose_name='Prix')
description = models.TextField(blank=True, verbose_name="Description")
thumbnail = models.ImageField(upload_to="products", blank=True, null=True, verbose_name='Image produit')
promo = models.BooleanField(default=False, verbose_name="Produit en promotion")
percent = models.IntegerField(default=0, verbose_name='Pourcentage promotion')
promo_date_end = models.DateField(blank=True, null=True, verbose_name='Date fin de promotion')
class Meta:
verbose_name = "Viande"
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
Dans mon gabarit j'ai essayé intuitivement ceci :
{% if productMeat.promo == True %}
<p>{{ productMeat.price - ( productMeat.promo * ProductMeat.percent / 100 }}</p>
<p>Fin de la promotion le : {{ productMeat.promo.date.end }}</p>
{% endif %}
La seconde maniere et la si je m'approche de la vérité en faisant comme ceci c'est de créer la fonction
promotion je ne sais pas quoi mettre dans le return, voici le code du model avec la fonction promotion :
class ProductMeat(models.Model):
title = models.CharField(max_length=38, unique=True, verbose_name="Viande")
slug = models.SlugField(max_length=38, unique=True, blank=True)
price = models.FloatField(default=0.0, verbose_name='Prix')
description = models.TextField(blank=True, verbose_name="Description")
thumbnail = models.ImageField(upload_to="products", blank=True, null=True, verbose_name='Image produit')
promo = models.BooleanField(default=False, verbose_name="Produit en promotion")
percent = models.IntegerField(default=0, verbose_name='Pourcentage promotion')
promo_date_end = models.DateField(blank=True, null=True, verbose_name='Date fin de promotion')
class Meta:
verbose_name = "Viande"
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def promotion(request):
if (ProductMeat.promo == True):
totalPromo = ProductMeat.price - (ProductMeat.price * ProductMeat.percent / 100)
return totalPromo
Sur discord on ma orienté vers les filtres personnalisés avec add mais j'ai beau lire la doc je pense que je n'ai pas assez d'expérience encore dans python pour discerner de quoi j'ai besoin...
Merci d'avance, bonne jouréne.
Yann
Salut Yann,
Alors en règle générale, il est préférable de faire le maximum au niveau de ton modèle. Évite à tout prix de faire des calculs complexes comme ça directement dans le template HTML, c'est dur à lire, tu es beaucoup plus limité qu'en Python, et c'est pas pratique si tu souhaites ré-utiliser cela ailleurs.
En général, il est préférable de faire tout ça en premier dans ton modèle, sinon dans ta vue, et en dernier lieu dans ton template.
Autre point important à garder en tête : un modèle ça reste une classe Python. Même s'il y a plein de choses que tu peux faire par la suite avec le langage de Queryset de Django, ça n'en reste pas moins une simple classe.
Du coup tu peux faire tout ce que tu fais avec une classe normale, notamment créer des méthodes ou des propriétés.
C'est de ce côté là dans ton cas que tu dois regarder et tu y es presque arrivé, le seul problème c'est que tu as mélangé les vues (fonctions) et ton modèle. Pas besoin ici de mettre request en paramètre, par contre le self est important (car tu es dans une méthode de ta classe et tu souhaites accéder à l'instance et ses attributs).
Donc dans ton cas, tu peux simplement modifier ta méthode et la passer en propriété de cette façon :
class ProductMeat(models.Model):
title = models.CharField(max_length=38, unique=True, verbose_name="Viande")
slug = models.SlugField(max_length=38, unique=True, blank=True)
price = models.FloatField(default=0.0, verbose_name='Prix')
description = models.TextField(blank=True, verbose_name="Description")
thumbnail = models.ImageField(upload_to="products", blank=True, null=True, verbose_name='Image produit')
promo = models.BooleanField(default=False, verbose_name="Produit en promotion")
percent = models.IntegerField(default=0, verbose_name='Pourcentage promotion')
promo_date_end = models.DateField(blank=True, null=True, verbose_name='Date fin de promotion')
class Meta:
verbose_name = "Viande"
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
@property
def price_with_promotion(self):
if self.promo:
return self.price - (self.price * self.percent / 100)
return self.price
Et dans ton template :
{% if productMeat.promo %}
<p>{{ productMeat.price_with_promotion }}</p>
<p>Fin de la promotion le : {{ productMeat.promo_date_end }}</p>
{% endif %}
J'espère que c'est plus clair pour toi :)
De ce que j'ai retenu pour appelé une fonction qui est dans un class automatiquement utilisé self pour qu'elle utilise les objects de la class ou elle se situe.Avec selfj'appel l'object concerné pour l'utilisé dans ma fonction. Et on l'appel dans le template avec @property. J'aurai du revoir la vidéo sur les requêtes dans les models.
Je te conseille de revoir cette vidéo et lire cet article pour bien comprendre self.
Et le @property n'est pas obligatoire dans ce cas-ci, tu pourrais juste faire une méthode et l'appeler de toute façon de la même façon car dans le langage de gabarit de Django, tu ne dois pas mettre les parenthèses.
Dans ce cas-ci il est préférable tout de même d'utiliser un @property car tu calcules / créé un nouvel attribut à partir d'attributs existants, donc c'est plus logique en terme d'utilisation.
Merci encore plus clair !
Inscris-toi
(c'est gratuit !)
Tu dois créer un compte pour participer aux discussions.
Créer un compte