Search code examples
pythonpython-3.xdjangomodel

If statement in Django Model related to an other model


I'm building a Django Python App and I am facing a problem. For some reason, I would like to implement a different price (Produit.PU_HT_WH) according to the customer (client) type (retailer or wholesaler (booleans). I would like to implement it to my models.py so that I don't have to changes

Models.py (Produit) :

class Produit(models.Model):
    id_Prod = models.CharField(max_length=200, null=True)
    EAN = models.IntegerField()
    PU_HT_WH = models.FloatField(null=True)
    denomination = models.CharField(max_length=200, null=True)
    
    def __str__(self):
        return self.id_Prod
    
    
    def PU_HT(self):
        if self.client.retailer:
            PU_HT= (self.PU_HT_WH/ 0.85) 
        else :
            PU_HT = self.PU_HT_WH
        return PU_HT

Models.py (Client) :

class Client(models.Model):
    id_Client = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
    nom_client = models.CharField(max_length=200, null=True)
    prenom_client = models.CharField(max_length=200, null=True)
    raison_sociale = models.CharField(max_length=200, null=True)
    retailer =  models.BooleanField(default=False, null=True)
    
    def __str__(self):
        return self.nom_client

My goal here is that I just have to replace every " {{prod.PU_HT_WH|floatformat:2}}€ " to " {{prod.PU_HT|floatformat:2}}€ " to display prices according to the customer. The website works only on @login_required so I would like that the customer only sees his price.

I hope that I've been enough understandable ! Thanks for every tips that you could give me :)

I've tried many ways but I always have an error on that line :

if self.client.retailer : 

I don't konw if it is because I am not giving the good boolean check or if it is just impossible to have an if condition regarding to another class , even in an def.

Thanks again for your help


Solution

  • Two Ways:

    1. Initialize Product with a member variable called Client. This doesn't need to be a column as client will be decided on runtime.
    class Product(SafeDeleteModel):
        id_Prod = models.CharField(max_length=200, null=True)
        EAN = models.IntegerField()
        PU_HT_WH = models.FloatField(null=True)
        denomination = models.CharField(max_length=200, null=True)
    
        def __init__(self, client: RandomClient, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.client = client
    
        def __str__(self):
            return self.id_Prod
    
        def PU_HT(self):
            PU_HT = self.PU_HT_WH
            if self.client.retailer:
                PU_HT = (self.PU_HT_WH / 0.85)
            return PU_HT
    

    tested as follows:

    @pytest.mark.django_db()
    def test_pricing():
        client = RandomClient(retailer=True)
        client.save()
        product = Product(client=client)
        product.PU_HT_WH = 100
        product.EAN = "12345"
        product.save()
        assert product.PU_HT() == 117.64705882352942
    
    1. Do this in a class method which takes client as an input.
    class Product(SafeDeleteModel):
        id_Prod = models.CharField(max_length=200, null=True)
        EAN = models.IntegerField()
        PU_HT_WH = models.FloatField(null=True)
        denomination = models.CharField(max_length=200, null=True)
    
        def __str__(self):
            return self.id_Prod
    
        def PU_HT(self, client: RandomClient):
            PU_HT = self.PU_HT_WH
            if client.retailer:
                PU_HT = (self.PU_HT_WH / 0.85)
            return PU_HT
    

    tested as:

    @pytest.mark.django_db()
    def test_pricing():
        client = RandomClient(retailer=True)
        client.save()
        product = Product()
        product.PU_HT_WH = 100
        product.EAN = "12345"
        product.save()
        assert product.PU_HT(client) == 117.64705882352942
    

    If I were to pick between the two, I'd pick the second method to do this. Product is a separate entity with a few things that change it's behaviour according to the client. The fact that the function takes client as an input is a good indication of this dependence.