Résolue

Création d'une formule de promotion (dur dur)

# Affichage # Django

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.

Thibault houdon

Mentor

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

Inscris-toi

Tu dois créer un compte pour participer aux discussions.

Créer un compte

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.